Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / autocomplete / search_provider_unittest.cc
1 // Copyright 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/search_provider.h"
6
7 #include <string>
8
9 #include "base/command_line.h"
10 #include "base/metrics/field_trial.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/run_loop.h"
13 #include "base/strings/string16.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/time/time.h"
18 #include "build/build_config.h"
19 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
20 #include "chrome/browser/autocomplete/autocomplete_controller.h"
21 #include "chrome/browser/autocomplete/autocomplete_input.h"
22 #include "chrome/browser/autocomplete/autocomplete_match.h"
23 #include "chrome/browser/autocomplete/autocomplete_provider.h"
24 #include "chrome/browser/autocomplete/autocomplete_provider_listener.h"
25 #include "chrome/browser/autocomplete/history_url_provider.h"
26 #include "chrome/browser/history/history_service.h"
27 #include "chrome/browser/history/history_service_factory.h"
28 #include "chrome/browser/omnibox/omnibox_field_trial.h"
29 #include "chrome/browser/search_engines/search_engine_type.h"
30 #include "chrome/browser/search_engines/template_url.h"
31 #include "chrome/browser/search_engines/template_url_service.h"
32 #include "chrome/browser/search_engines/template_url_service_factory.h"
33 #include "chrome/browser/signin/signin_manager_factory.h"
34 #include "chrome/browser/sync/profile_sync_service.h"
35 #include "chrome/browser/sync/profile_sync_service_factory.h"
36 #include "chrome/common/chrome_switches.h"
37 #include "chrome/common/metrics/variations/variations_util.h"
38 #include "chrome/common/pref_names.h"
39 #include "chrome/test/base/testing_browser_process.h"
40 #include "chrome/test/base/testing_profile.h"
41 #include "components/signin/core/browser/signin_manager.h"
42 #include "components/sync_driver/pref_names.h"
43 #include "components/variations/entropy_provider.h"
44 #include "content/public/test/test_browser_thread_bundle.h"
45 #include "net/url_request/test_url_fetcher_factory.h"
46 #include "net/url_request/url_request_status.h"
47 #include "testing/gtest/include/gtest/gtest.h"
48
49 using base::ASCIIToUTF16;
50
51 namespace {
52
53 // Returns the first match in |matches| with |allowed_to_be_default_match|
54 // set to true.
55 ACMatches::const_iterator FindDefaultMatch(const ACMatches& matches) {
56   ACMatches::const_iterator it = matches.begin();
57   while ((it != matches.end()) && !it->allowed_to_be_default_match)
58     ++it;
59   return it;
60 }
61
62 class SuggestionDeletionHandler;
63 class SearchProviderForTest : public SearchProvider {
64  public:
65   SearchProviderForTest(
66       AutocompleteProviderListener* listener,
67       Profile* profile);
68   bool is_success() { return is_success_; };
69
70  protected:
71   virtual ~SearchProviderForTest();
72
73  private:
74   virtual void RecordDeletionResult(bool success) OVERRIDE;
75   bool is_success_;
76   DISALLOW_COPY_AND_ASSIGN(SearchProviderForTest);
77 };
78
79 SearchProviderForTest::SearchProviderForTest(
80     AutocompleteProviderListener* listener,
81     Profile* profile)
82     : SearchProvider(listener, profile), is_success_(false) {
83 }
84
85 SearchProviderForTest::~SearchProviderForTest() {
86 }
87
88 void SearchProviderForTest::RecordDeletionResult(bool success) {
89   is_success_ = success;
90 }
91
92 } // namespace
93
94 // SearchProviderTest ---------------------------------------------------------
95
96 // The following environment is configured for these tests:
97 // . The TemplateURL default_t_url_ is set as the default provider.
98 // . The TemplateURL keyword_t_url_ is added to the TemplateURLService. This
99 //   TemplateURL has a valid suggest and search URL.
100 // . The URL created by using the search term term1_ with default_t_url_ is
101 //   added to history.
102 // . The URL created by using the search term keyword_term_ with keyword_t_url_
103 //   is added to history.
104 // . test_factory_ is set as the URLFetcherFactory.
105 class SearchProviderTest : public testing::Test,
106                            public AutocompleteProviderListener {
107  public:
108   struct ResultInfo {
109     ResultInfo() : result_type(AutocompleteMatchType::NUM_TYPES),
110                    allowed_to_be_default_match(false) {
111     }
112     ResultInfo(GURL gurl,
113                AutocompleteMatch::Type result_type,
114                bool allowed_to_be_default_match,
115                base::string16 fill_into_edit)
116       : gurl(gurl),
117         result_type(result_type),
118         allowed_to_be_default_match(allowed_to_be_default_match),
119         fill_into_edit(fill_into_edit) {
120     }
121
122     const GURL gurl;
123     const AutocompleteMatch::Type result_type;
124     const bool allowed_to_be_default_match;
125     const base::string16 fill_into_edit;
126   };
127
128   struct TestData {
129     const base::string16 input;
130     const size_t num_results;
131     const ResultInfo output[3];
132   };
133
134   SearchProviderTest()
135       : default_t_url_(NULL),
136         term1_(ASCIIToUTF16("term1")),
137         keyword_t_url_(NULL),
138         keyword_term_(ASCIIToUTF16("keyword")),
139         run_loop_(NULL) {
140     ResetFieldTrialList();
141   }
142
143   // See description above class for what this registers.
144   virtual void SetUp() OVERRIDE;
145   virtual void TearDown() OVERRIDE;
146
147   void RunTest(TestData* cases, int num_cases, bool prefer_keyword);
148
149  protected:
150   // Needed for AutocompleteFieldTrial::ActivateStaticTrials();
151   scoped_ptr<base::FieldTrialList> field_trial_list_;
152
153   // Default value used for testing.
154   static const std::string kNotApplicable;
155
156   // Adds a search for |term|, using the engine |t_url| to the history, and
157   // returns the URL for that search.
158   GURL AddSearchToHistory(TemplateURL* t_url, base::string16 term, int visit_count);
159
160   // Looks for a match in |provider_| with |contents| equal to |contents|.
161   // Sets |match| to it if found.  Returns whether |match| was set.
162   bool FindMatchWithContents(const base::string16& contents,
163                              AutocompleteMatch* match);
164
165   // Looks for a match in |provider_| with destination |url|.  Sets |match| to
166   // it if found.  Returns whether |match| was set.
167   bool FindMatchWithDestination(const GURL& url, AutocompleteMatch* match);
168
169   // AutocompleteProviderListener:
170   // If we're waiting for the provider to finish, this exits the message loop.
171   virtual void OnProviderUpdate(bool updated_matches) OVERRIDE;
172
173   // Runs a nested message loop until provider_ is done. The message loop is
174   // exited by way of OnProviderUpdate.
175   void RunTillProviderDone();
176
177   // Invokes Start on provider_, then runs all pending tasks.
178   void QueryForInput(const base::string16& text,
179                      bool prevent_inline_autocomplete,
180                      bool prefer_keyword);
181
182   // Calls QueryForInput(), finishes any suggest query, then if |wyt_match| is
183   // non-NULL, sets it to the "what you typed" entry for |text|.
184   void QueryForInputAndSetWYTMatch(const base::string16& text,
185                                    AutocompleteMatch* wyt_match);
186
187   // Notifies the URLFetcher for the suggest query corresponding to the default
188   // search provider that it's done.
189   // Be sure and wrap calls to this in ASSERT_NO_FATAL_FAILURE.
190   void FinishDefaultSuggestQuery();
191
192   // Runs SearchProvider on |input|, for which the suggest server replies
193   // with |json|, and expects that the resulting matches' contents equals
194   // that in |matches|.  An empty entry in |matches| means no match should
195   // be returned in that position.  Reports any errors with a message that
196   // includes |error_description|.
197   void ForcedQueryTestHelper(const std::string& input,
198                              const std::string& json,
199                              const std::string matches[3],
200                              const std::string& error_description);
201
202   void ResetFieldTrialList();
203
204   void ClearAllResults();
205
206   // See description above class for details of these fields.
207   TemplateURL* default_t_url_;
208   const base::string16 term1_;
209   GURL term1_url_;
210   TemplateURL* keyword_t_url_;
211   const base::string16 keyword_term_;
212   GURL keyword_url_;
213
214   content::TestBrowserThreadBundle thread_bundle_;
215
216   // URLFetcherFactory implementation registered.
217   net::TestURLFetcherFactory test_factory_;
218
219   // Profile we use.
220   TestingProfile profile_;
221
222   // The provider.
223   scoped_refptr<SearchProviderForTest> provider_;
224
225   // If non-NULL, OnProviderUpdate quits the current |run_loop_|.
226   base::RunLoop* run_loop_;
227
228   DISALLOW_COPY_AND_ASSIGN(SearchProviderTest);
229 };
230
231 // static
232 const std::string SearchProviderTest::kNotApplicable = "Not Applicable";
233
234 void SearchProviderTest::SetUp() {
235   // Make sure that fetchers are automatically ungregistered upon destruction.
236   test_factory_.set_remove_fetcher_on_delete(true);
237
238   // We need both the history service and template url model loaded.
239   ASSERT_TRUE(profile_.CreateHistoryService(true, false));
240   TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
241       &profile_, &TemplateURLServiceFactory::BuildInstanceFor);
242
243   TemplateURLService* turl_model =
244       TemplateURLServiceFactory::GetForProfile(&profile_);
245
246   turl_model->Load();
247
248   // Reset the default TemplateURL.
249   TemplateURLData data;
250   data.short_name = ASCIIToUTF16("t");
251   data.SetURL("http://defaultturl/{searchTerms}");
252   data.suggestions_url = "http://defaultturl2/{searchTerms}";
253   data.instant_url = "http://does/not/exist?strk=1";
254   data.search_terms_replacement_key = "strk";
255   default_t_url_ = new TemplateURL(&profile_, data);
256   turl_model->Add(default_t_url_);
257   turl_model->SetUserSelectedDefaultSearchProvider(default_t_url_);
258   TemplateURLID default_provider_id = default_t_url_->id();
259   ASSERT_NE(0, default_provider_id);
260
261   // Add url1, with search term term1_.
262   term1_url_ = AddSearchToHistory(default_t_url_, term1_, 1);
263
264   // Create another TemplateURL.
265   data.short_name = ASCIIToUTF16("k");
266   data.SetKeyword(ASCIIToUTF16("k"));
267   data.SetURL("http://keyword/{searchTerms}");
268   data.suggestions_url = "http://suggest_keyword/{searchTerms}";
269   keyword_t_url_ = new TemplateURL(&profile_, data);
270   turl_model->Add(keyword_t_url_);
271   ASSERT_NE(0, keyword_t_url_->id());
272
273   // Add a page and search term for keyword_t_url_.
274   keyword_url_ = AddSearchToHistory(keyword_t_url_, keyword_term_, 1);
275
276   // Keywords are updated by the InMemoryHistoryBackend only after the message
277   // has been processed on the history thread. Block until history processes all
278   // requests to ensure the InMemoryDatabase is the state we expect it.
279   profile_.BlockUntilHistoryProcessesPendingRequests();
280
281   provider_ = new SearchProviderForTest(this, &profile_);
282   provider_->kMinimumTimeBetweenSuggestQueriesMs = 0;
283 }
284
285 void SearchProviderTest::TearDown() {
286   base::RunLoop().RunUntilIdle();
287
288   // Shutdown the provider before the profile.
289   provider_ = NULL;
290 }
291
292 void SearchProviderTest::RunTest(TestData* cases,
293                                  int num_cases,
294                                  bool prefer_keyword) {
295   ACMatches matches;
296   for (int i = 0; i < num_cases; ++i) {
297     AutocompleteInput input(cases[i].input, base::string16::npos,
298                             base::string16(), GURL(),
299                             AutocompleteInput::INVALID_SPEC, false,
300                             prefer_keyword, true, true);
301     provider_->Start(input, false);
302     matches = provider_->matches();
303     base::string16 diagnostic_details =
304         ASCIIToUTF16("Input was: ") +
305         cases[i].input +
306         ASCIIToUTF16("; prefer_keyword was: ") +
307         (prefer_keyword ? ASCIIToUTF16("true") : ASCIIToUTF16("false"));
308     EXPECT_EQ(cases[i].num_results, matches.size()) << diagnostic_details;
309     if (matches.size() == cases[i].num_results) {
310       for (size_t j = 0; j < cases[i].num_results; ++j) {
311         EXPECT_EQ(cases[i].output[j].gurl, matches[j].destination_url) <<
312             diagnostic_details;
313         EXPECT_EQ(cases[i].output[j].result_type, matches[j].type) <<
314             diagnostic_details;
315         EXPECT_EQ(cases[i].output[j].fill_into_edit,
316                   matches[j].fill_into_edit) << diagnostic_details;
317         EXPECT_EQ(cases[i].output[j].allowed_to_be_default_match,
318                   matches[j].allowed_to_be_default_match) << diagnostic_details;
319       }
320     }
321   }
322 }
323
324 void SearchProviderTest::OnProviderUpdate(bool updated_matches) {
325   if (run_loop_ && provider_->done()) {
326     run_loop_->Quit();
327     run_loop_ = NULL;
328   }
329 }
330
331 void SearchProviderTest::RunTillProviderDone() {
332   if (provider_->done())
333     return;
334
335   base::RunLoop run_loop;
336   run_loop_ = &run_loop;
337   run_loop.Run();
338 }
339
340 void SearchProviderTest::QueryForInput(const base::string16& text,
341                                        bool prevent_inline_autocomplete,
342                                        bool prefer_keyword) {
343   // Start a query.
344   AutocompleteInput input(text, base::string16::npos, base::string16(), GURL(),
345                           AutocompleteInput::INVALID_SPEC,
346                           prevent_inline_autocomplete, prefer_keyword, true,
347                           true);
348   provider_->Start(input, false);
349
350   // RunUntilIdle so that the task scheduled by SearchProvider to create the
351   // URLFetchers runs.
352   base::RunLoop().RunUntilIdle();
353 }
354
355 void SearchProviderTest::QueryForInputAndSetWYTMatch(
356     const base::string16& text,
357     AutocompleteMatch* wyt_match) {
358   QueryForInput(text, false, false);
359   profile_.BlockUntilHistoryProcessesPendingRequests();
360   ASSERT_NO_FATAL_FAILURE(FinishDefaultSuggestQuery());
361   if (!wyt_match)
362     return;
363   ASSERT_GE(provider_->matches().size(), 1u);
364   EXPECT_TRUE(FindMatchWithDestination(GURL(
365       default_t_url_->url_ref().ReplaceSearchTerms(
366           TemplateURLRef::SearchTermsArgs(base::CollapseWhitespace(
367               text, false)))),
368       wyt_match));
369 }
370
371 GURL SearchProviderTest::AddSearchToHistory(TemplateURL* t_url,
372                                             base::string16 term,
373                                             int visit_count) {
374   HistoryService* history =
375       HistoryServiceFactory::GetForProfile(&profile_,
376                                            Profile::EXPLICIT_ACCESS);
377   GURL search(t_url->url_ref().ReplaceSearchTerms(
378       TemplateURLRef::SearchTermsArgs(term)));
379   static base::Time last_added_time;
380   last_added_time = std::max(base::Time::Now(),
381       last_added_time + base::TimeDelta::FromMicroseconds(1));
382   history->AddPageWithDetails(search, base::string16(), visit_count, visit_count,
383       last_added_time, false, history::SOURCE_BROWSED);
384   history->SetKeywordSearchTermsForURL(search, t_url->id(), term);
385   return search;
386 }
387
388 bool SearchProviderTest::FindMatchWithContents(const base::string16& contents,
389                                                AutocompleteMatch* match) {
390   for (ACMatches::const_iterator i = provider_->matches().begin();
391        i != provider_->matches().end(); ++i) {
392     if (i->contents == contents) {
393       *match = *i;
394       return true;
395     }
396   }
397   return false;
398 }
399
400 bool SearchProviderTest::FindMatchWithDestination(const GURL& url,
401                                                   AutocompleteMatch* match) {
402   for (ACMatches::const_iterator i = provider_->matches().begin();
403        i != provider_->matches().end(); ++i) {
404     if (i->destination_url == url) {
405       *match = *i;
406       return true;
407     }
408   }
409   return false;
410 }
411
412 void SearchProviderTest::FinishDefaultSuggestQuery() {
413   net::TestURLFetcher* default_fetcher =
414       test_factory_.GetFetcherByID(
415           SearchProvider::kDefaultProviderURLFetcherID);
416   ASSERT_TRUE(default_fetcher);
417
418   // Tell the SearchProvider the default suggest query is done.
419   default_fetcher->set_response_code(200);
420   default_fetcher->delegate()->OnURLFetchComplete(default_fetcher);
421 }
422
423 void SearchProviderTest::ForcedQueryTestHelper(
424     const std::string& input,
425     const std::string& json,
426     const std::string expected_matches[3],
427     const std::string& error_description) {
428   QueryForInput(ASCIIToUTF16(input), false, false);
429   net::TestURLFetcher* fetcher = test_factory_.GetFetcherByID(
430       SearchProvider::kDefaultProviderURLFetcherID);
431   ASSERT_TRUE(fetcher);
432   fetcher->set_response_code(200);
433   fetcher->SetResponseString(json);
434   fetcher->delegate()->OnURLFetchComplete(fetcher);
435   RunTillProviderDone();
436
437   const ACMatches& matches = provider_->matches();
438   ASSERT_LE(matches.size(), 3u);
439   size_t i = 0;
440   // Ensure that the returned matches equal the expectations.
441   for (; i < matches.size(); ++i) {
442     EXPECT_EQ(ASCIIToUTF16(expected_matches[i]), matches[i].contents) <<
443         error_description;
444   }
445   // Ensure that no expected matches are missing.
446   for (; i < 3u; ++i) {
447     EXPECT_EQ(std::string(), expected_matches[i]) <<
448         "Case #" << i << ": " << error_description;
449   }
450 }
451
452 void SearchProviderTest::ResetFieldTrialList() {
453   // Destroy the existing FieldTrialList before creating a new one to avoid
454   // a DCHECK.
455   field_trial_list_.reset();
456   field_trial_list_.reset(new base::FieldTrialList(
457       new metrics::SHA1EntropyProvider("foo")));
458   chrome_variations::testing::ClearAllVariationParams();
459   base::FieldTrial* trial = base::FieldTrialList::CreateFieldTrial(
460       "AutocompleteDynamicTrial_0", "DefaultGroup");
461   trial->group();
462 }
463
464 void SearchProviderTest::ClearAllResults() {
465   provider_->ClearAllResults();
466 }
467
468 // Actual Tests ---------------------------------------------------------------
469
470 // Make sure we query history for the default provider and a URLFetcher is
471 // created for the default provider suggest results.
472 TEST_F(SearchProviderTest, QueryDefaultProvider) {
473   base::string16 term = term1_.substr(0, term1_.length() - 1);
474   QueryForInput(term, false, false);
475
476   // Make sure the default providers suggest service was queried.
477   net::TestURLFetcher* fetcher = test_factory_.GetFetcherByID(
478       SearchProvider::kDefaultProviderURLFetcherID);
479   ASSERT_TRUE(fetcher);
480
481   // And the URL matches what we expected.
482   GURL expected_url(default_t_url_->suggestions_url_ref().ReplaceSearchTerms(
483       TemplateURLRef::SearchTermsArgs(term)));
484   ASSERT_TRUE(fetcher->GetOriginalURL() == expected_url);
485
486   // Tell the SearchProvider the suggest query is done.
487   fetcher->set_response_code(200);
488   fetcher->delegate()->OnURLFetchComplete(fetcher);
489   fetcher = NULL;
490
491   // Run till the history results complete.
492   RunTillProviderDone();
493
494   // The SearchProvider is done. Make sure it has a result for the history
495   // term term1.
496   AutocompleteMatch term1_match;
497   EXPECT_TRUE(FindMatchWithDestination(term1_url_, &term1_match));
498   // Term1 should not have a description, it's set later.
499   EXPECT_TRUE(term1_match.description.empty());
500
501   AutocompleteMatch wyt_match;
502   EXPECT_TRUE(FindMatchWithDestination(
503       GURL(default_t_url_->url_ref().ReplaceSearchTerms(
504           TemplateURLRef::SearchTermsArgs(term))), &wyt_match));
505   EXPECT_TRUE(wyt_match.description.empty());
506
507   // The match for term1 should be more relevant than the what you typed match.
508   EXPECT_GT(term1_match.relevance, wyt_match.relevance);
509   // This longer match should be inlineable.
510   EXPECT_TRUE(term1_match.allowed_to_be_default_match);
511   // The what you typed match should be too, of course.
512   EXPECT_TRUE(wyt_match.allowed_to_be_default_match);
513 }
514
515 TEST_F(SearchProviderTest, HonorPreventInlineAutocomplete) {
516   base::string16 term = term1_.substr(0, term1_.length() - 1);
517   QueryForInput(term, true, false);
518
519   ASSERT_FALSE(provider_->matches().empty());
520   ASSERT_EQ(AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
521             provider_->matches()[0].type);
522   EXPECT_TRUE(provider_->matches()[0].allowed_to_be_default_match);
523 }
524
525 // Issues a query that matches the registered keyword and makes sure history
526 // is queried as well as URLFetchers getting created.
527 TEST_F(SearchProviderTest, QueryKeywordProvider) {
528   base::string16 term = keyword_term_.substr(0, keyword_term_.length() - 1);
529   QueryForInput(keyword_t_url_->keyword() + ASCIIToUTF16(" ") + term,
530                 false,
531                 false);
532
533   // Make sure the default providers suggest service was queried.
534   net::TestURLFetcher* default_fetcher = test_factory_.GetFetcherByID(
535       SearchProvider::kDefaultProviderURLFetcherID);
536   ASSERT_TRUE(default_fetcher);
537
538   // Tell the SearchProvider the default suggest query is done.
539   default_fetcher->set_response_code(200);
540   default_fetcher->delegate()->OnURLFetchComplete(default_fetcher);
541   default_fetcher = NULL;
542
543   // Make sure the keyword providers suggest service was queried.
544   net::TestURLFetcher* keyword_fetcher = test_factory_.GetFetcherByID(
545       SearchProvider::kKeywordProviderURLFetcherID);
546   ASSERT_TRUE(keyword_fetcher);
547
548   // And the URL matches what we expected.
549   GURL expected_url(keyword_t_url_->suggestions_url_ref().ReplaceSearchTerms(
550       TemplateURLRef::SearchTermsArgs(term)));
551   ASSERT_TRUE(keyword_fetcher->GetOriginalURL() == expected_url);
552
553   // Tell the SearchProvider the keyword suggest query is done.
554   keyword_fetcher->set_response_code(200);
555   keyword_fetcher->delegate()->OnURLFetchComplete(keyword_fetcher);
556   keyword_fetcher = NULL;
557
558   // Run till the history results complete.
559   RunTillProviderDone();
560
561   // The SearchProvider is done. Make sure it has a result for the history
562   // term keyword.
563   AutocompleteMatch match;
564   EXPECT_TRUE(FindMatchWithDestination(keyword_url_, &match));
565
566   // The match should have an associated keyword.
567   EXPECT_FALSE(match.keyword.empty());
568
569   // The fill into edit should contain the keyword.
570   EXPECT_EQ(keyword_t_url_->keyword() + base::char16(' ') + keyword_term_,
571             match.fill_into_edit);
572 }
573
574 TEST_F(SearchProviderTest, DontSendPrivateDataToSuggest) {
575   // None of the following input strings should be sent to the suggest server,
576   // because they may contain private data.
577   const char* inputs[] = {
578     "username:password",
579     "http://username:password",
580     "https://username:password",
581     "username:password@hostname",
582     "http://username:password@hostname/",
583     "file://filename",
584     "data://data",
585     "unknownscheme:anything",
586     "http://hostname/?query=q",
587     "http://hostname/path#ref",
588     "http://hostname/path #ref",
589     "https://hostname/path",
590   };
591
592   for (size_t i = 0; i < arraysize(inputs); ++i) {
593     QueryForInput(ASCIIToUTF16(inputs[i]), false, false);
594     // Make sure the default provider's suggest service was not queried.
595     ASSERT_TRUE(test_factory_.GetFetcherByID(
596         SearchProvider::kDefaultProviderURLFetcherID) == NULL);
597     // Run till the history results complete.
598     RunTillProviderDone();
599   }
600 }
601
602 TEST_F(SearchProviderTest, SendNonPrivateDataToSuggest) {
603   // All of the following input strings should be sent to the suggest server,
604   // because they should not get caught by the private data checks.
605   const char* inputs[] = {
606     "query",
607     "query with spaces",
608     "http://hostname",
609     "http://hostname/path",
610     "http://hostname #ref",
611     "www.hostname.com #ref",
612     "https://hostname",
613     "#hashtag",
614     "foo https://hostname/path"
615   };
616
617   profile_.BlockUntilHistoryProcessesPendingRequests();
618   for (size_t i = 0; i < arraysize(inputs); ++i) {
619     QueryForInput(ASCIIToUTF16(inputs[i]), false, false);
620     // Make sure the default provider's suggest service was queried.
621     ASSERT_TRUE(test_factory_.GetFetcherByID(
622         SearchProvider::kDefaultProviderURLFetcherID) != NULL);
623   }
624 }
625
626 TEST_F(SearchProviderTest, DontAutocompleteURLLikeTerms) {
627   AutocompleteClassifierFactory::GetInstance()->SetTestingFactoryAndUse(
628       &profile_, &AutocompleteClassifierFactory::BuildInstanceFor);
629   GURL url = AddSearchToHistory(default_t_url_,
630                                 ASCIIToUTF16("docs.google.com"), 1);
631
632   // Add the term as a url.
633   HistoryServiceFactory::GetForProfile(&profile_, Profile::EXPLICIT_ACCESS)->
634       AddPageWithDetails(GURL("http://docs.google.com"), base::string16(), 1, 1,
635                          base::Time::Now(), false, history::SOURCE_BROWSED);
636   profile_.BlockUntilHistoryProcessesPendingRequests();
637
638   AutocompleteMatch wyt_match;
639   ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch(ASCIIToUTF16("docs"),
640                                                       &wyt_match));
641
642   // There should be two matches, one for what you typed, the other for
643   // 'docs.google.com'. The search term should have a lower priority than the
644   // what you typed match.
645   ASSERT_EQ(2u, provider_->matches().size());
646   AutocompleteMatch term_match;
647   EXPECT_TRUE(FindMatchWithDestination(url, &term_match));
648   EXPECT_GT(wyt_match.relevance, term_match.relevance);
649   EXPECT_TRUE(wyt_match.allowed_to_be_default_match);
650   EXPECT_TRUE(term_match.allowed_to_be_default_match);
651 }
652
653 TEST_F(SearchProviderTest, DontGiveNavsuggestionsInForcedQueryMode) {
654   const std::string kEmptyMatch;
655   struct {
656     const std::string json;
657     const std::string matches_in_default_mode[3];
658     const std::string matches_in_forced_query_mode[3];
659   } cases[] = {
660     // Without suggested relevance scores.
661     { "[\"a\",[\"http://a1.com\", \"a2\"],[],[],"
662        "{\"google:suggesttype\":[\"NAVIGATION\", \"QUERY\"]}]",
663       { "a", "a1.com", "a2" },
664       { "a", "a2", kEmptyMatch } },
665
666     // With suggested relevance scores in a situation where navsuggest would
667     // go second.
668     { "[\"a\",[\"http://a1.com\", \"a2\"],[],[],"
669        "{\"google:suggesttype\":[\"NAVIGATION\", \"QUERY\"],"
670         "\"google:suggestrelevance\":[1250, 1200]}]",
671       { "a", "a1.com", "a2" },
672       { "a", "a2", kEmptyMatch } },
673
674     // With suggested relevance scores in a situation where navsuggest
675     // would go first.
676     { "[\"a\",[\"http://a1.com\", \"a2\"],[],[],"
677        "{\"google:suggesttype\":[\"NAVIGATION\", \"QUERY\"],"
678         "\"google:suggestrelevance\":[1350, 1250]}]",
679       { "a1.com", "a", "a2" },
680       { "a", "a2", kEmptyMatch } },
681
682     // With suggested relevance scores in a situation where navsuggest
683     // would go first only because verbatim has been demoted.
684     { "[\"a\",[\"http://a1.com\", \"a2\"],[],[],"
685        "{\"google:suggesttype\":[\"NAVIGATION\", \"QUERY\"],"
686         "\"google:suggestrelevance\":[1450, 1400],"
687         "\"google:verbatimrelevance\":1350}]",
688       { "a1.com", "a2", "a" },
689       { "a2", "a", kEmptyMatch } },
690   };
691
692   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
693     ForcedQueryTestHelper("a", cases[i].json, cases[i].matches_in_default_mode,
694                            "regular input with json=" + cases[i].json);
695     ForcedQueryTestHelper("?a", cases[i].json,
696                           cases[i].matches_in_forced_query_mode,
697                           "forced query input with json=" + cases[i].json);
698   }
699 }
700
701 // A multiword search with one visit should not autocomplete until multiple
702 // words are typed.
703 TEST_F(SearchProviderTest, DontAutocompleteUntilMultipleWordsTyped) {
704   GURL term_url(AddSearchToHistory(default_t_url_, ASCIIToUTF16("one search"),
705                                    1));
706   profile_.BlockUntilHistoryProcessesPendingRequests();
707
708   AutocompleteMatch wyt_match;
709   ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch(ASCIIToUTF16("on"),
710                                                       &wyt_match));
711   ASSERT_EQ(2u, provider_->matches().size());
712   AutocompleteMatch term_match;
713   EXPECT_TRUE(FindMatchWithDestination(term_url, &term_match));
714   EXPECT_GT(wyt_match.relevance, term_match.relevance);
715   EXPECT_TRUE(wyt_match.allowed_to_be_default_match);
716   EXPECT_TRUE(term_match.allowed_to_be_default_match);
717
718   ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch(ASCIIToUTF16("one se"),
719                                                       &wyt_match));
720   ASSERT_EQ(2u, provider_->matches().size());
721   EXPECT_TRUE(FindMatchWithDestination(term_url, &term_match));
722   EXPECT_GT(term_match.relevance, wyt_match.relevance);
723   EXPECT_TRUE(term_match.allowed_to_be_default_match);
724   EXPECT_TRUE(wyt_match.allowed_to_be_default_match);
725 }
726
727 // A multiword search with more than one visit should autocomplete immediately.
728 TEST_F(SearchProviderTest, AutocompleteMultipleVisitsImmediately) {
729   GURL term_url(AddSearchToHistory(default_t_url_, ASCIIToUTF16("two searches"),
730                                    2));
731   profile_.BlockUntilHistoryProcessesPendingRequests();
732
733   AutocompleteMatch wyt_match;
734   ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch(ASCIIToUTF16("tw"),
735                                                       &wyt_match));
736   ASSERT_EQ(2u, provider_->matches().size());
737   AutocompleteMatch term_match;
738   EXPECT_TRUE(FindMatchWithDestination(term_url, &term_match));
739   EXPECT_GT(term_match.relevance, wyt_match.relevance);
740   EXPECT_TRUE(term_match.allowed_to_be_default_match);
741   EXPECT_TRUE(wyt_match.allowed_to_be_default_match);
742 }
743
744 // Autocompletion should work at a word boundary after a space, and should
745 // offer a suggestion for the trimmed search query.
746 TEST_F(SearchProviderTest, AutocompleteAfterSpace) {
747   AddSearchToHistory(default_t_url_, ASCIIToUTF16("two  searches "), 2);
748   GURL suggested_url(default_t_url_->url_ref().ReplaceSearchTerms(
749       TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("two searches"))));
750   profile_.BlockUntilHistoryProcessesPendingRequests();
751
752   AutocompleteMatch wyt_match;
753   ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch(ASCIIToUTF16("two "),
754                                                       &wyt_match));
755   ASSERT_EQ(2u, provider_->matches().size());
756   AutocompleteMatch term_match;
757   EXPECT_TRUE(FindMatchWithDestination(suggested_url, &term_match));
758   EXPECT_GT(term_match.relevance, wyt_match.relevance);
759   EXPECT_TRUE(term_match.allowed_to_be_default_match);
760   EXPECT_EQ(ASCIIToUTF16("searches"), term_match.inline_autocompletion);
761   EXPECT_EQ(ASCIIToUTF16("two searches"), term_match.fill_into_edit);
762   EXPECT_TRUE(wyt_match.allowed_to_be_default_match);
763 }
764
765 // Newer multiword searches should score more highly than older ones.
766 TEST_F(SearchProviderTest, ScoreNewerSearchesHigher) {
767   GURL term_url_a(AddSearchToHistory(default_t_url_,
768                                      ASCIIToUTF16("three searches aaa"), 1));
769   GURL term_url_b(AddSearchToHistory(default_t_url_,
770                                      ASCIIToUTF16("three searches bbb"), 1));
771   profile_.BlockUntilHistoryProcessesPendingRequests();
772
773   AutocompleteMatch wyt_match;
774   ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch(ASCIIToUTF16("three se"),
775                                                       &wyt_match));
776   ASSERT_EQ(3u, provider_->matches().size());
777   AutocompleteMatch term_match_a;
778   EXPECT_TRUE(FindMatchWithDestination(term_url_a, &term_match_a));
779   AutocompleteMatch term_match_b;
780   EXPECT_TRUE(FindMatchWithDestination(term_url_b, &term_match_b));
781   EXPECT_GT(term_match_b.relevance, term_match_a.relevance);
782   EXPECT_GT(term_match_a.relevance, wyt_match.relevance);
783   EXPECT_TRUE(term_match_b.allowed_to_be_default_match);
784   EXPECT_TRUE(term_match_a.allowed_to_be_default_match);
785   EXPECT_TRUE(wyt_match.allowed_to_be_default_match);
786 }
787
788 // An autocompleted multiword search should not be replaced by a different
789 // autocompletion while the user is still typing a valid prefix.
790 TEST_F(SearchProviderTest, DontReplacePreviousAutocompletion) {
791   GURL term_url_a(AddSearchToHistory(default_t_url_,
792                                      ASCIIToUTF16("four searches aaa"), 2));
793   GURL term_url_b(AddSearchToHistory(default_t_url_,
794                                      ASCIIToUTF16("four searches bbb"), 1));
795   profile_.BlockUntilHistoryProcessesPendingRequests();
796
797   AutocompleteMatch wyt_match;
798   ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch(ASCIIToUTF16("fo"),
799                                                       &wyt_match));
800   ASSERT_EQ(3u, provider_->matches().size());
801   AutocompleteMatch term_match_a;
802   EXPECT_TRUE(FindMatchWithDestination(term_url_a, &term_match_a));
803   AutocompleteMatch term_match_b;
804   EXPECT_TRUE(FindMatchWithDestination(term_url_b, &term_match_b));
805   EXPECT_GT(term_match_a.relevance, wyt_match.relevance);
806   EXPECT_GT(wyt_match.relevance, term_match_b.relevance);
807   EXPECT_TRUE(term_match_a.allowed_to_be_default_match);
808   EXPECT_TRUE(term_match_b.allowed_to_be_default_match);
809   EXPECT_TRUE(wyt_match.allowed_to_be_default_match);
810
811   ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch(ASCIIToUTF16("four se"),
812                                                       &wyt_match));
813   ASSERT_EQ(3u, provider_->matches().size());
814   EXPECT_TRUE(FindMatchWithDestination(term_url_a, &term_match_a));
815   EXPECT_TRUE(FindMatchWithDestination(term_url_b, &term_match_b));
816   EXPECT_GT(term_match_a.relevance, wyt_match.relevance);
817   EXPECT_GT(wyt_match.relevance, term_match_b.relevance);
818   EXPECT_TRUE(term_match_a.allowed_to_be_default_match);
819   EXPECT_TRUE(term_match_b.allowed_to_be_default_match);
820   EXPECT_TRUE(wyt_match.allowed_to_be_default_match);
821 }
822
823 // Non-completable multiword searches should not crowd out single-word searches.
824 TEST_F(SearchProviderTest, DontCrowdOutSingleWords) {
825   GURL term_url(AddSearchToHistory(default_t_url_, ASCIIToUTF16("five"), 1));
826   AddSearchToHistory(default_t_url_, ASCIIToUTF16("five searches bbb"), 1);
827   AddSearchToHistory(default_t_url_, ASCIIToUTF16("five searches ccc"), 1);
828   AddSearchToHistory(default_t_url_, ASCIIToUTF16("five searches ddd"), 1);
829   AddSearchToHistory(default_t_url_, ASCIIToUTF16("five searches eee"), 1);
830   profile_.BlockUntilHistoryProcessesPendingRequests();
831
832   AutocompleteMatch wyt_match;
833   ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch(ASCIIToUTF16("fi"),
834                                                       &wyt_match));
835   ASSERT_EQ(AutocompleteProvider::kMaxMatches + 1, provider_->matches().size());
836   AutocompleteMatch term_match;
837   EXPECT_TRUE(FindMatchWithDestination(term_url, &term_match));
838   EXPECT_GT(term_match.relevance, wyt_match.relevance);
839   EXPECT_TRUE(term_match.allowed_to_be_default_match);
840   EXPECT_TRUE(wyt_match.allowed_to_be_default_match);
841 }
842
843 // Inline autocomplete matches regardless of case differences from the input.
844 TEST_F(SearchProviderTest, InlineMixedCaseMatches) {
845   GURL term_url(AddSearchToHistory(default_t_url_, ASCIIToUTF16("FOO"), 1));
846   profile_.BlockUntilHistoryProcessesPendingRequests();
847
848   AutocompleteMatch wyt_match;
849   ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch(ASCIIToUTF16("f"),
850                                                       &wyt_match));
851   ASSERT_EQ(2u, provider_->matches().size());
852   AutocompleteMatch term_match;
853   EXPECT_TRUE(FindMatchWithDestination(term_url, &term_match));
854   EXPECT_GT(term_match.relevance, wyt_match.relevance);
855   EXPECT_EQ(ASCIIToUTF16("FOO"), term_match.fill_into_edit);
856   EXPECT_EQ(ASCIIToUTF16("OO"), term_match.inline_autocompletion);
857   EXPECT_TRUE(term_match.allowed_to_be_default_match);
858 }
859
860 // Verifies AutocompleteControllers return results (including keyword
861 // results) in the right order and set descriptions for them correctly.
862 TEST_F(SearchProviderTest, KeywordOrderingAndDescriptions) {
863   // Add an entry that corresponds to a keyword search with 'term2'.
864   AddSearchToHistory(keyword_t_url_, ASCIIToUTF16("term2"), 1);
865   profile_.BlockUntilHistoryProcessesPendingRequests();
866
867   AutocompleteController controller(&profile_, NULL,
868       AutocompleteProvider::TYPE_SEARCH);
869   controller.Start(AutocompleteInput(
870       ASCIIToUTF16("k t"), base::string16::npos, base::string16(), GURL(),
871       AutocompleteInput::INVALID_SPEC, false, false, true, true));
872   const AutocompleteResult& result = controller.result();
873
874   // There should be three matches, one for the keyword history, one for
875   // keyword provider's what-you-typed, and one for the default provider's
876   // what you typed, in that order.
877   ASSERT_EQ(3u, result.size());
878   EXPECT_EQ(AutocompleteMatchType::SEARCH_HISTORY, result.match_at(0).type);
879   EXPECT_EQ(AutocompleteMatchType::SEARCH_OTHER_ENGINE,
880             result.match_at(1).type);
881   EXPECT_EQ(AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
882             result.match_at(2).type);
883   EXPECT_GT(result.match_at(0).relevance, result.match_at(1).relevance);
884   EXPECT_GT(result.match_at(1).relevance, result.match_at(2).relevance);
885   EXPECT_TRUE(result.match_at(0).allowed_to_be_default_match);
886   EXPECT_TRUE(result.match_at(1).allowed_to_be_default_match);
887   EXPECT_FALSE(result.match_at(2).allowed_to_be_default_match);
888
889   // The two keyword results should come with the keyword we expect.
890   EXPECT_EQ(ASCIIToUTF16("k"), result.match_at(0).keyword);
891   EXPECT_EQ(ASCIIToUTF16("k"), result.match_at(1).keyword);
892   // The default provider has a different keyword.  (We don't explicitly
893   // set it during this test, so all we do is assert that it's different.)
894   EXPECT_NE(result.match_at(0).keyword, result.match_at(2).keyword);
895
896   // The top result will always have a description.  The third result,
897   // coming from a different provider than the first two, should also.
898   // Whether the second result has one doesn't matter much.  (If it was
899   // missing, people would infer that it's the same search provider as
900   // the one above it.)
901   EXPECT_FALSE(result.match_at(0).description.empty());
902   EXPECT_FALSE(result.match_at(2).description.empty());
903   EXPECT_NE(result.match_at(0).description, result.match_at(2).description);
904 }
905
906 TEST_F(SearchProviderTest, KeywordVerbatim) {
907   TestData cases[] = {
908     // Test a simple keyword input.
909     { ASCIIToUTF16("k foo"), 2,
910       { ResultInfo(GURL("http://keyword/foo"),
911                    AutocompleteMatchType::SEARCH_OTHER_ENGINE,
912                    true,
913                    ASCIIToUTF16("k foo")),
914         ResultInfo(GURL("http://defaultturl/k%20foo"),
915                    AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
916                    false,
917                    ASCIIToUTF16("k foo") ) } },
918
919     // Make sure extra whitespace after the keyword doesn't change the
920     // keyword verbatim query.  Also verify that interior consecutive
921     // whitespace gets trimmed.
922     { ASCIIToUTF16("k   foo"), 2,
923       { ResultInfo(GURL("http://keyword/foo"),
924                    AutocompleteMatchType::SEARCH_OTHER_ENGINE,
925                    true,
926                    ASCIIToUTF16("k foo")),
927         ResultInfo(GURL("http://defaultturl/k%20foo"),
928                    AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
929                    false,
930                    ASCIIToUTF16("k foo")) } },
931     // Leading whitespace should be stripped before SearchProvider gets the
932     // input; hence there are no tests here about how it handles those inputs.
933
934     // Verify that interior consecutive whitespace gets trimmed in either case.
935     { ASCIIToUTF16("k  foo  bar"), 2,
936       { ResultInfo(GURL("http://keyword/foo%20bar"),
937                    AutocompleteMatchType::SEARCH_OTHER_ENGINE,
938                    true,
939                    ASCIIToUTF16("k foo bar")),
940         ResultInfo(GURL("http://defaultturl/k%20foo%20bar"),
941                    AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
942                    false,
943                    ASCIIToUTF16("k foo bar")) } },
944
945     // Verify that trailing whitespace gets trimmed.
946     { ASCIIToUTF16("k foo bar  "), 2,
947       { ResultInfo(GURL("http://keyword/foo%20bar"),
948                    AutocompleteMatchType::SEARCH_OTHER_ENGINE,
949                    true,
950                    ASCIIToUTF16("k foo bar")),
951         ResultInfo(GURL("http://defaultturl/k%20foo%20bar"),
952                    AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
953                    false,
954                    ASCIIToUTF16("k foo bar")) } },
955
956     // Keywords can be prefixed by certain things that should get ignored
957     // when constructing the keyword match.
958     { ASCIIToUTF16("www.k foo"), 2,
959       { ResultInfo(GURL("http://keyword/foo"),
960                    AutocompleteMatchType::SEARCH_OTHER_ENGINE,
961                    true,
962                    ASCIIToUTF16("k foo")),
963         ResultInfo(GURL("http://defaultturl/www.k%20foo"),
964                    AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
965                    false,
966                    ASCIIToUTF16("www.k foo")) } },
967     { ASCIIToUTF16("http://k foo"), 2,
968       { ResultInfo(GURL("http://keyword/foo"),
969                    AutocompleteMatchType::SEARCH_OTHER_ENGINE,
970                    true,
971                    ASCIIToUTF16("k foo")),
972         ResultInfo(GURL("http://defaultturl/http%3A//k%20foo"),
973                    AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
974                    false,
975                    ASCIIToUTF16("http://k foo")) } },
976     { ASCIIToUTF16("http://www.k foo"), 2,
977       { ResultInfo(GURL("http://keyword/foo"),
978                    AutocompleteMatchType::SEARCH_OTHER_ENGINE,
979                    true,
980                    ASCIIToUTF16("k foo")),
981         ResultInfo(GURL("http://defaultturl/http%3A//www.k%20foo"),
982                    AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
983                    false,
984                    ASCIIToUTF16("http://www.k foo")) } },
985
986     // A keyword with no remaining input shouldn't get a keyword
987     // verbatim match.
988     { ASCIIToUTF16("k"), 1,
989       { ResultInfo(GURL("http://defaultturl/k"),
990                    AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
991                    true,
992                    ASCIIToUTF16("k")) } },
993     // Ditto.  Trailing whitespace shouldn't make a difference.
994     { ASCIIToUTF16("k "), 1,
995       { ResultInfo(GURL("http://defaultturl/k"),
996                    AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
997                    true,
998                    ASCIIToUTF16("k")) } }
999
1000     // The fact that verbatim queries to keyword are handled by KeywordProvider
1001     // not SearchProvider is tested in
1002     // chrome/browser/extensions/api/omnibox/omnibox_apitest.cc.
1003   };
1004
1005   // Test not in keyword mode.
1006   RunTest(cases, arraysize(cases), false);
1007
1008   // Test in keyword mode.  (Both modes should give the same result.)
1009   RunTest(cases, arraysize(cases), true);
1010 }
1011
1012 // Ensures command-line flags are reflected in the URLs the search provider
1013 // generates.
1014 TEST_F(SearchProviderTest, CommandLineOverrides) {
1015   TemplateURLService* turl_model =
1016       TemplateURLServiceFactory::GetForProfile(&profile_);
1017
1018   TemplateURLData data;
1019   data.short_name = ASCIIToUTF16("default");
1020   data.SetKeyword(data.short_name);
1021   data.SetURL("{google:baseURL}{searchTerms}");
1022   default_t_url_ = new TemplateURL(&profile_, data);
1023   turl_model->Add(default_t_url_);
1024   turl_model->SetUserSelectedDefaultSearchProvider(default_t_url_);
1025
1026   CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kGoogleBaseURL,
1027                                                       "http://www.bar.com/");
1028   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1029       switches::kExtraSearchQueryParams, "a=b");
1030
1031   TestData cases[] = {
1032     { ASCIIToUTF16("k a"), 2,
1033       { ResultInfo(GURL("http://keyword/a"),
1034                    AutocompleteMatchType::SEARCH_OTHER_ENGINE,
1035                    true,
1036                    ASCIIToUTF16("k a")),
1037         ResultInfo(GURL("http://www.bar.com/k%20a?a=b"),
1038                    AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
1039                    false,
1040                    ASCIIToUTF16("k a")) } },
1041   };
1042
1043   RunTest(cases, arraysize(cases), false);
1044 }
1045
1046 // Verifies Navsuggest results don't set a TemplateURL, which Instant relies on.
1047 // Also verifies that just the *first* navigational result is listed as a match
1048 // if suggested relevance scores were not sent.
1049 TEST_F(SearchProviderTest, NavSuggestNoSuggestedRelevanceScores) {
1050   QueryForInput(ASCIIToUTF16("a.c"), false, false);
1051
1052   // Make sure the default providers suggest service was queried.
1053   net::TestURLFetcher* fetcher = test_factory_.GetFetcherByID(
1054       SearchProvider::kDefaultProviderURLFetcherID);
1055   ASSERT_TRUE(fetcher);
1056
1057   // Tell the SearchProvider the suggest query is done.
1058   fetcher->set_response_code(200);
1059   fetcher->SetResponseString(
1060       "[\"a.c\",[\"a.com\", \"a.com/b\"],[\"a\", \"b\"],[],"
1061       "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\"]}]");
1062   fetcher->delegate()->OnURLFetchComplete(fetcher);
1063   fetcher = NULL;
1064
1065   // Run till the history results complete.
1066   RunTillProviderDone();
1067
1068   // Make sure the only match is 'a.com' and it doesn't have a template_url.
1069   AutocompleteMatch nav_match;
1070   EXPECT_TRUE(FindMatchWithDestination(GURL("http://a.com"), &nav_match));
1071   EXPECT_TRUE(nav_match.keyword.empty());
1072   EXPECT_TRUE(nav_match.allowed_to_be_default_match);
1073   EXPECT_FALSE(FindMatchWithDestination(GURL("http://a.com/b"), &nav_match));
1074 }
1075
1076 // Verifies that the most relevant suggest results are added properly.
1077 TEST_F(SearchProviderTest, SuggestRelevance) {
1078   QueryForInput(ASCIIToUTF16("a"), false, false);
1079
1080   // Make sure the default provider's suggest service was queried.
1081   net::TestURLFetcher* fetcher = test_factory_.GetFetcherByID(
1082       SearchProvider::kDefaultProviderURLFetcherID);
1083   ASSERT_TRUE(fetcher);
1084
1085   // Tell the SearchProvider the suggest query is done.
1086   fetcher->set_response_code(200);
1087   fetcher->SetResponseString("[\"a\",[\"a1\", \"a2\", \"a3\", \"a4\"]]");
1088   fetcher->delegate()->OnURLFetchComplete(fetcher);
1089   fetcher = NULL;
1090
1091   // Run till the history results complete.
1092   RunTillProviderDone();
1093
1094   // Check the expected verbatim and (first 3) suggestions' relative relevances.
1095   AutocompleteMatch verbatim, match_a1, match_a2, match_a3, match_a4;
1096   EXPECT_TRUE(FindMatchWithContents(ASCIIToUTF16("a"), &verbatim));
1097   EXPECT_TRUE(FindMatchWithContents(ASCIIToUTF16("a1"), &match_a1));
1098   EXPECT_TRUE(FindMatchWithContents(ASCIIToUTF16("a2"), &match_a2));
1099   EXPECT_TRUE(FindMatchWithContents(ASCIIToUTF16("a3"), &match_a3));
1100   EXPECT_FALSE(FindMatchWithContents(ASCIIToUTF16("a4"), &match_a4));
1101   EXPECT_GT(verbatim.relevance, match_a1.relevance);
1102   EXPECT_GT(match_a1.relevance, match_a2.relevance);
1103   EXPECT_GT(match_a2.relevance, match_a3.relevance);
1104   EXPECT_TRUE(verbatim.allowed_to_be_default_match);
1105   EXPECT_TRUE(match_a1.allowed_to_be_default_match);
1106   EXPECT_TRUE(match_a2.allowed_to_be_default_match);
1107   EXPECT_TRUE(match_a3.allowed_to_be_default_match);
1108 }
1109
1110 // Verifies that the default provider abandons suggested relevance scores
1111 // when in keyword mode.  This should happen regardless of whether the
1112 // keyword provider returns suggested relevance scores.
1113 TEST_F(SearchProviderTest, DefaultProviderNoSuggestRelevanceInKeywordMode) {
1114   struct {
1115     const std::string default_provider_json;
1116     const std::string keyword_provider_json;
1117     const std::string matches[5];
1118   } cases[] = {
1119     // First, try an input where the keyword provider does not deliver
1120     // suggested relevance scores.
1121     { "[\"k a\",[\"k adefault-query\", \"adefault.com\"],[],[],"
1122       "{\"google:verbatimrelevance\":9700,"
1123       "\"google:suggesttype\":[\"QUERY\", \"NAVIGATION\"],"
1124       "\"google:suggestrelevance\":[9900, 9800]}]",
1125       "[\"a\",[\"akeyword-query\"],[],[],{\"google:suggesttype\":[\"QUERY\"]}]",
1126       { "a", "akeyword-query", "k a", "adefault.com", "k adefault-query" } },
1127
1128     // Now try with keyword provider suggested relevance scores.
1129     { "[\"k a\",[\"k adefault-query\", \"adefault.com\"],[],[],"
1130       "{\"google:verbatimrelevance\":9700,"
1131       "\"google:suggesttype\":[\"QUERY\", \"NAVIGATION\"],"
1132       "\"google:suggestrelevance\":[9900, 9800]}]",
1133       "[\"a\",[\"akeyword-query\"],[],[],{\"google:suggesttype\":[\"QUERY\"],"
1134       "\"google:verbatimrelevance\":9500,"
1135       "\"google:suggestrelevance\":[9600]}]",
1136       { "akeyword-query", "a", "k a", "adefault.com", "k adefault-query" } }
1137   };
1138
1139   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
1140     QueryForInput(ASCIIToUTF16("k a"), false, true);
1141     net::TestURLFetcher* default_fetcher =
1142         test_factory_.GetFetcherByID(
1143             SearchProvider::kDefaultProviderURLFetcherID);
1144     ASSERT_TRUE(default_fetcher);
1145     default_fetcher->set_response_code(200);
1146     default_fetcher->SetResponseString(cases[i].default_provider_json);
1147     default_fetcher->delegate()->OnURLFetchComplete(default_fetcher);
1148     net::TestURLFetcher* keyword_fetcher =
1149         test_factory_.GetFetcherByID(
1150             SearchProvider::kKeywordProviderURLFetcherID);
1151     ASSERT_TRUE(keyword_fetcher);
1152     keyword_fetcher->set_response_code(200);
1153     keyword_fetcher->SetResponseString(cases[i].keyword_provider_json);
1154     keyword_fetcher->delegate()->OnURLFetchComplete(keyword_fetcher);
1155     RunTillProviderDone();
1156
1157     const std::string description = "for input with default_provider_json=" +
1158         cases[i].default_provider_json + " and keyword_provider_json=" +
1159         cases[i].keyword_provider_json;
1160     const ACMatches& matches = provider_->matches();
1161     ASSERT_LE(matches.size(), ARRAYSIZE_UNSAFE(cases[i].matches));
1162     size_t j = 0;
1163     // Ensure that the returned matches equal the expectations.
1164     for (; j < matches.size(); ++j) {
1165       EXPECT_EQ(ASCIIToUTF16(cases[i].matches[j]), matches[j].contents) <<
1166           description;
1167     }
1168     // Ensure that no expected matches are missing.
1169     for (; j < ARRAYSIZE_UNSAFE(cases[i].matches); ++j)
1170       EXPECT_EQ(std::string(), cases[i].matches[j]) << description;
1171   }
1172 }
1173
1174 // Verifies that suggest results with relevance scores are added
1175 // properly when using the default fetcher.  When adding a new test
1176 // case to this test, please consider adding it to the tests in
1177 // KeywordFetcherSuggestRelevance below.
1178 TEST_F(SearchProviderTest, DefaultFetcherSuggestRelevance) {
1179   struct DefaultFetcherMatch {
1180     std::string contents;
1181     bool allowed_to_be_default_match;
1182   };
1183   const DefaultFetcherMatch kEmptyMatch = { kNotApplicable, false };
1184   struct {
1185     const std::string json;
1186     const DefaultFetcherMatch matches[6];
1187     const std::string inline_autocompletion;
1188   } cases[] = {
1189     // Ensure that suggestrelevance scores reorder matches.
1190     { "[\"a\",[\"b\", \"c\"],[],[],{\"google:suggestrelevance\":[1, 2]}]",
1191       { { "a", true }, { "c", false }, { "b", false }, kEmptyMatch, kEmptyMatch,
1192         kEmptyMatch },
1193       std::string() },
1194     { "[\"a\",[\"http://b.com\", \"http://c.com\"],[],[],"
1195        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\"],"
1196         "\"google:suggestrelevance\":[1, 2]}]",
1197       { { "a", true }, { "c.com", false }, { "b.com", false }, kEmptyMatch,
1198         kEmptyMatch, kEmptyMatch },
1199       std::string() },
1200
1201     // Without suggested relevance scores, we should only allow one
1202     // navsuggest result to be be displayed.
1203     { "[\"a\",[\"http://b.com\", \"http://c.com\"],[],[],"
1204        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\"]}]",
1205       { { "a", true }, { "b.com", false }, kEmptyMatch, kEmptyMatch,
1206         kEmptyMatch, kEmptyMatch },
1207       std::string() },
1208
1209     // Ensure that verbatimrelevance scores reorder or suppress verbatim.
1210     // Negative values will have no effect; the calculated value will be used.
1211     { "[\"a\",[\"a1\"],[],[],{\"google:verbatimrelevance\":9999,"
1212                              "\"google:suggestrelevance\":[9998]}]",
1213       { { "a", true}, { "a1", true }, kEmptyMatch, kEmptyMatch, kEmptyMatch,
1214         kEmptyMatch },
1215       std::string() },
1216     { "[\"a\",[\"a1\"],[],[],{\"google:verbatimrelevance\":9998,"
1217                              "\"google:suggestrelevance\":[9999]}]",
1218       { { "a1", true }, { "a", true }, kEmptyMatch, kEmptyMatch, kEmptyMatch,
1219         kEmptyMatch },
1220       "1" },
1221     { "[\"a\",[\"a1\"],[],[],{\"google:verbatimrelevance\":0,"
1222                              "\"google:suggestrelevance\":[9999]}]",
1223       { { "a1", true }, kEmptyMatch, kEmptyMatch, kEmptyMatch, kEmptyMatch,
1224         kEmptyMatch },
1225       "1" },
1226     { "[\"a\",[\"a1\"],[],[],{\"google:verbatimrelevance\":-1,"
1227                              "\"google:suggestrelevance\":[9999]}]",
1228       { { "a1", true }, { "a", true }, kEmptyMatch, kEmptyMatch, kEmptyMatch,
1229         kEmptyMatch },
1230       "1" },
1231     { "[\"a\",[\"http://a.com\"],[],[],"
1232        "{\"google:suggesttype\":[\"NAVIGATION\"],"
1233         "\"google:verbatimrelevance\":9999,"
1234         "\"google:suggestrelevance\":[9998]}]",
1235       { { "a", true }, { "a.com", true }, kEmptyMatch, kEmptyMatch, kEmptyMatch,
1236         kEmptyMatch },
1237       std::string() },
1238     { "[\"a\",[\"http://a.com\"],[],[],"
1239        "{\"google:suggesttype\":[\"NAVIGATION\"],"
1240         "\"google:verbatimrelevance\":9998,"
1241         "\"google:suggestrelevance\":[9999]}]",
1242       { { "a.com", true }, { "a", true }, kEmptyMatch, kEmptyMatch, kEmptyMatch,
1243         kEmptyMatch },
1244       ".com" },
1245     { "[\"a\",[\"http://a.com\"],[],[],"
1246        "{\"google:suggesttype\":[\"NAVIGATION\"],"
1247         "\"google:verbatimrelevance\":0,"
1248         "\"google:suggestrelevance\":[9999]}]",
1249       { { "a.com", true }, kEmptyMatch, kEmptyMatch, kEmptyMatch, kEmptyMatch,
1250         kEmptyMatch },
1251       ".com" },
1252     { "[\"a\",[\"http://a.com\"],[],[],"
1253        "{\"google:suggesttype\":[\"NAVIGATION\"],"
1254         "\"google:verbatimrelevance\":-1,"
1255         "\"google:suggestrelevance\":[9999]}]",
1256       { { "a.com", true }, { "a", true }, kEmptyMatch, kEmptyMatch, kEmptyMatch,
1257         kEmptyMatch },
1258       ".com" },
1259
1260     // Ensure that both types of relevance scores reorder matches together.
1261     { "[\"a\",[\"a1\", \"a2\"],[],[],{\"google:suggestrelevance\":[9999, 9997],"
1262                                      "\"google:verbatimrelevance\":9998}]",
1263       { { "a1", true }, { "a", true }, { "a2", true }, kEmptyMatch, kEmptyMatch,
1264         kEmptyMatch },
1265       "1" },
1266
1267     // Allow non-inlineable matches to be the highest-scoring match but,
1268     // if the result set lacks a single inlineable result, abandon suggested
1269     // relevance scores entirely.
1270     { "[\"a\",[\"b\"],[],[],{\"google:suggestrelevance\":[9999]}]",
1271       { { "b", false }, { "a", true }, kEmptyMatch, kEmptyMatch, kEmptyMatch,
1272         kEmptyMatch },
1273       std::string() },
1274     { "[\"a\",[\"b\"],[],[],{\"google:suggestrelevance\":[9999],"
1275                             "\"google:verbatimrelevance\":0}]",
1276       { { "a", true }, { "b", false }, kEmptyMatch, kEmptyMatch, kEmptyMatch,
1277         kEmptyMatch },
1278       std::string() },
1279     { "[\"a\",[\"http://b.com\"],[],[],"
1280        "{\"google:suggesttype\":[\"NAVIGATION\"],"
1281         "\"google:suggestrelevance\":[9999]}]",
1282       { { "b.com", false }, { "a", true }, kEmptyMatch, kEmptyMatch,
1283         kEmptyMatch, kEmptyMatch },
1284       std::string() },
1285     { "[\"a\",[\"http://b.com\"],[],[],"
1286        "{\"google:suggesttype\":[\"NAVIGATION\"],"
1287         "\"google:suggestrelevance\":[9999],"
1288         "\"google:verbatimrelevance\":0}]",
1289       { { "a", true }, { "b.com", false }, kEmptyMatch, kEmptyMatch,
1290         kEmptyMatch, kEmptyMatch },
1291       std::string() },
1292
1293     // Allow low-scoring matches.
1294     { "[\"a\",[\"a1\"],[],[],{\"google:verbatimrelevance\":0}]",
1295       { { "a1", true }, kEmptyMatch, kEmptyMatch, kEmptyMatch, kEmptyMatch,
1296         kEmptyMatch },
1297       "1" },
1298     { "[\"a\",[\"a1\"],[],[],{\"google:verbatimrelevance\":1}]",
1299       { { "a1", true }, { "a", true }, kEmptyMatch, kEmptyMatch, kEmptyMatch,
1300         kEmptyMatch },
1301       "1" },
1302     { "[\"a\",[\"a1\"],[],[],{\"google:suggestrelevance\":[1],"
1303                              "\"google:verbatimrelevance\":0}]",
1304       { { "a1", true }, kEmptyMatch, kEmptyMatch, kEmptyMatch, kEmptyMatch,
1305         kEmptyMatch },
1306       "1" },
1307     { "[\"a\",[\"a1\", \"a2\"],[],[],{\"google:suggestrelevance\":[1, 2],"
1308                                      "\"google:verbatimrelevance\":0}]",
1309       { { "a2", true }, { "a1", true }, kEmptyMatch, kEmptyMatch, kEmptyMatch,
1310         kEmptyMatch },
1311       "2" },
1312     { "[\"a\",[\"a1\", \"a2\"],[],[],{\"google:suggestrelevance\":[1, 3],"
1313       "\"google:verbatimrelevance\":2}]",
1314       { { "a2", true }, { "a", true }, { "a1", true }, kEmptyMatch, kEmptyMatch,
1315         kEmptyMatch },
1316       "2" },
1317     { "[\"a\",[\"http://a.com\"],[],[],"
1318        "{\"google:suggesttype\":[\"NAVIGATION\"],"
1319         "\"google:suggestrelevance\":[1],"
1320         "\"google:verbatimrelevance\":0}]",
1321       { { "a.com", true }, kEmptyMatch, kEmptyMatch, kEmptyMatch, kEmptyMatch,
1322         kEmptyMatch },
1323       ".com" },
1324     { "[\"a\",[\"http://a1.com\", \"http://a2.com\"],[],[],"
1325        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\"],"
1326         "\"google:suggestrelevance\":[1, 2],"
1327         "\"google:verbatimrelevance\":0}]",
1328       { { "a2.com", true }, { "a1.com", true }, kEmptyMatch, kEmptyMatch,
1329         kEmptyMatch, kEmptyMatch },
1330       "2.com" },
1331
1332     // Ensure that all suggestions are considered, regardless of order.
1333     { "[\"a\",[\"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"],[],[],"
1334        "{\"google:suggestrelevance\":[1, 2, 3, 4, 5, 6, 7]}]",
1335       { { "a", true }, { "h", false }, { "g", false }, { "f", false },
1336         { "e", false }, { "d", false } },
1337       std::string() },
1338     { "[\"a\",[\"http://b.com\", \"http://c.com\", \"http://d.com\","
1339               "\"http://e.com\", \"http://f.com\", \"http://g.com\","
1340               "\"http://h.com\"],[],[],"
1341        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\","
1342                                 "\"NAVIGATION\", \"NAVIGATION\","
1343                                 "\"NAVIGATION\", \"NAVIGATION\","
1344                                 "\"NAVIGATION\"],"
1345         "\"google:suggestrelevance\":[1, 2, 3, 4, 5, 6, 7]}]",
1346       { { "a", true }, { "h.com", false }, { "g.com", false },
1347         { "f.com", false }, { "e.com", false }, { "d.com", false } },
1348       std::string() },
1349
1350     // Ensure that incorrectly sized suggestion relevance lists are ignored.
1351     { "[\"a\",[\"a1\", \"a2\"],[],[],{\"google:suggestrelevance\":[1]}]",
1352       { { "a", true }, { "a1", true }, { "a2", true }, kEmptyMatch, kEmptyMatch,
1353         kEmptyMatch },
1354       std::string() },
1355     { "[\"a\",[\"a1\"],[],[],{\"google:suggestrelevance\":[9999, 1]}]",
1356       { { "a", true }, { "a1", true }, kEmptyMatch, kEmptyMatch, kEmptyMatch,
1357         kEmptyMatch },
1358       std::string() },
1359     { "[\"a\",[\"http://a1.com\", \"http://a2.com\"],[],[],"
1360        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\"],"
1361         "\"google:suggestrelevance\":[1]}]",
1362       { { "a", true }, { "a1.com", true }, kEmptyMatch, kEmptyMatch,
1363         kEmptyMatch, kEmptyMatch },
1364       std::string() },
1365     { "[\"a\",[\"http://a1.com\"],[],[],"
1366        "{\"google:suggesttype\":[\"NAVIGATION\"],"
1367        "\"google:suggestrelevance\":[9999, 1]}]",
1368       { { "a", true }, { "a1.com", true }, kEmptyMatch, kEmptyMatch,
1369         kEmptyMatch, kEmptyMatch },
1370       std::string() },
1371
1372     // Ensure that all 'verbatim' results are merged with their maximum score.
1373     { "[\"a\",[\"a\", \"a1\", \"a2\"],[],[],"
1374        "{\"google:suggestrelevance\":[9998, 9997, 9999]}]",
1375       { { "a2", true }, { "a", true }, { "a1", true }, kEmptyMatch, kEmptyMatch,
1376         kEmptyMatch },
1377       "2" },
1378     { "[\"a\",[\"a\", \"a1\", \"a2\"],[],[],"
1379        "{\"google:suggestrelevance\":[9998, 9997, 9999],"
1380         "\"google:verbatimrelevance\":0}]",
1381       { { "a2", true }, { "a", true }, { "a1", true }, kEmptyMatch, kEmptyMatch,
1382         kEmptyMatch },
1383       "2" },
1384
1385     // Ensure that verbatim is always generated without other suggestions.
1386     // TODO(msw): Ensure verbatimrelevance is respected (except suppression).
1387     { "[\"a\",[],[],[],{\"google:verbatimrelevance\":1}]",
1388       { { "a", true }, kEmptyMatch, kEmptyMatch, kEmptyMatch, kEmptyMatch,
1389         kEmptyMatch },
1390       std::string() },
1391     { "[\"a\",[],[],[],{\"google:verbatimrelevance\":0}]",
1392       { { "a", true }, kEmptyMatch, kEmptyMatch, kEmptyMatch, kEmptyMatch,
1393         kEmptyMatch },
1394       std::string() },
1395   };
1396
1397   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
1398     QueryForInput(ASCIIToUTF16("a"), false, false);
1399     net::TestURLFetcher* fetcher =
1400         test_factory_.GetFetcherByID(
1401             SearchProvider::kDefaultProviderURLFetcherID);
1402     ASSERT_TRUE(fetcher);
1403     fetcher->set_response_code(200);
1404     fetcher->SetResponseString(cases[i].json);
1405     fetcher->delegate()->OnURLFetchComplete(fetcher);
1406     RunTillProviderDone();
1407
1408     const std::string description = "for input with json=" + cases[i].json;
1409     const ACMatches& matches = provider_->matches();
1410     ASSERT_FALSE(matches.empty());
1411     // Find the first match that's allowed to be the default match and check
1412     // its inline_autocompletion.
1413     ACMatches::const_iterator it = FindDefaultMatch(matches);
1414     ASSERT_NE(matches.end(), it);
1415     EXPECT_EQ(ASCIIToUTF16(cases[i].inline_autocompletion),
1416               it->inline_autocompletion) << description;
1417
1418     ASSERT_LE(matches.size(), ARRAYSIZE_UNSAFE(cases[i].matches));
1419     size_t j = 0;
1420     // Ensure that the returned matches equal the expectations.
1421     for (; j < matches.size(); ++j) {
1422       EXPECT_EQ(ASCIIToUTF16(cases[i].matches[j].contents),
1423                 matches[j].contents) << description;
1424       EXPECT_EQ(cases[i].matches[j].allowed_to_be_default_match,
1425                 matches[j].allowed_to_be_default_match) << description;
1426     }
1427     // Ensure that no expected matches are missing.
1428     for (; j < ARRAYSIZE_UNSAFE(cases[i].matches); ++j)
1429       EXPECT_EQ(kNotApplicable, cases[i].matches[j].contents) <<
1430           "Case # " << i << " " << description;
1431   }
1432 }
1433
1434 // Verifies that suggest results with relevance scores are added
1435 // properly when using the keyword fetcher.  This is similar to the
1436 // test DefaultFetcherSuggestRelevance above but this uses inputs that
1437 // trigger keyword suggestions (i.e., "k a" rather than "a") and has
1438 // different expectations (because now the results are a mix of
1439 // keyword suggestions and default provider suggestions).  When a new
1440 // test is added to this TEST_F, please consider if it would be
1441 // appropriate to add to DefaultFetcherSuggestRelevance as well.
1442 TEST_F(SearchProviderTest, KeywordFetcherSuggestRelevance) {
1443   struct KeywordFetcherMatch {
1444     std::string contents;
1445     bool from_keyword;
1446     bool allowed_to_be_default_match;
1447   };
1448   const KeywordFetcherMatch kEmptyMatch = { kNotApplicable, false, false };
1449   struct {
1450     const std::string json;
1451     const KeywordFetcherMatch matches[6];
1452     const std::string inline_autocompletion;
1453   } cases[] = {
1454     // Ensure that suggest relevance scores reorder matches and that
1455     // the keyword verbatim (lacking a suggested verbatim score) beats
1456     // the default provider verbatim.
1457     { "[\"a\",[\"b\", \"c\"],[],[],{\"google:suggestrelevance\":[1, 2]}]",
1458       { { "a",   true,  true },
1459         { "k a", false, false },
1460         { "c",   true,  false },
1461         { "b",   true,  false },
1462         kEmptyMatch, kEmptyMatch },
1463       std::string() },
1464     // Again, check that relevance scores reorder matches, just this
1465     // time with navigation matches.  This also checks that with
1466     // suggested relevance scores we allow multiple navsuggest results.
1467     // Note that navsuggest results that come from a keyword provider
1468     // are marked as not a keyword result.  (They don't go to a
1469     // keyword search engine.)
1470     { "[\"a\",[\"http://b.com\", \"http://c.com\", \"d\"],[],[],"
1471        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\", \"QUERY\"],"
1472        "\"google:suggestrelevance\":[1301, 1302, 1303]}]",
1473       { { "a",     true,  true },
1474         { "d",     true,  false },
1475         { "c.com", false, false },
1476         { "b.com", false, false },
1477         { "k a",   false, false },
1478         kEmptyMatch },
1479       std::string() },
1480
1481     // Without suggested relevance scores, we should only allow one
1482     // navsuggest result to be be displayed.
1483     { "[\"a\",[\"http://b.com\", \"http://c.com\"],[],[],"
1484        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\"]}]",
1485       { { "a",     true,  true },
1486         { "b.com", false, false },
1487         { "k a",   false, false },
1488         kEmptyMatch, kEmptyMatch, kEmptyMatch },
1489       std::string() },
1490
1491     // Ensure that verbatimrelevance scores reorder or suppress verbatim.
1492     // Negative values will have no effect; the calculated value will be used.
1493     { "[\"a\",[\"a1\"],[],[],{\"google:verbatimrelevance\":9999,"
1494                              "\"google:suggestrelevance\":[9998]}]",
1495       { { "a",   true,  true },
1496         { "a1",  true,  true },
1497         { "k a", false, false },
1498         kEmptyMatch, kEmptyMatch, kEmptyMatch },
1499       std::string() },
1500     { "[\"a\",[\"a1\"],[],[],{\"google:verbatimrelevance\":9998,"
1501                              "\"google:suggestrelevance\":[9999]}]",
1502       { { "a1",  true,  true },
1503         { "a",   true,  true },
1504         { "k a", false, false },
1505         kEmptyMatch, kEmptyMatch, kEmptyMatch },
1506       "1" },
1507     { "[\"a\",[\"a1\"],[],[],{\"google:verbatimrelevance\":0,"
1508                              "\"google:suggestrelevance\":[9999]}]",
1509       { { "a1",  true,  true },
1510         { "k a", false, false },
1511         kEmptyMatch, kEmptyMatch, kEmptyMatch, kEmptyMatch },
1512       "1" },
1513     { "[\"a\",[\"a1\"],[],[],{\"google:verbatimrelevance\":-1,"
1514                              "\"google:suggestrelevance\":[9999]}]",
1515       { { "a1",  true,  true },
1516         { "a",   true,  true },
1517         { "k a", false, false },
1518         kEmptyMatch, kEmptyMatch, kEmptyMatch },
1519       "1" },
1520     { "[\"a\",[\"http://a.com\"],[],[],"
1521        "{\"google:suggesttype\":[\"NAVIGATION\"],"
1522         "\"google:verbatimrelevance\":9999,"
1523         "\"google:suggestrelevance\":[9998]}]",
1524       { { "a",     true,  true },
1525         { "a.com", false, false },
1526         { "k a",   false, false },
1527         kEmptyMatch, kEmptyMatch, kEmptyMatch },
1528       std::string() },
1529
1530     // Ensure that both types of relevance scores reorder matches together.
1531     { "[\"a\",[\"a1\", \"a2\"],[],[],{\"google:suggestrelevance\":[9999, 9997],"
1532                                      "\"google:verbatimrelevance\":9998}]",
1533       { { "a1",  true,  true },
1534         { "a",   true,  true },
1535         { "a2",  true,  true },
1536         { "k a", false, false },
1537         kEmptyMatch, kEmptyMatch },
1538       "1" },
1539
1540     // Check that non-inlinable matches may be ranked as the highest result
1541     // if there is at least one inlineable match.
1542     { "[\"a\",[\"b\"],[],[],{\"google:suggestrelevance\":[9999]}]",
1543       { { "b",   true,  false },
1544         { "a",   true,  true },
1545         { "k a", false, false },
1546         kEmptyMatch, kEmptyMatch, kEmptyMatch },
1547       std::string() },
1548     { "[\"a\",[\"http://b.com\"],[],[],"
1549        "{\"google:suggesttype\":[\"NAVIGATION\"],"
1550         "\"google:suggestrelevance\":[9999]}]",
1551       { { "b.com", false, false },
1552         { "a",     true,  true },
1553         { "k a",   false, false },
1554         kEmptyMatch, kEmptyMatch, kEmptyMatch },
1555       std::string() },
1556     // On the other hand, if there is no inlineable match, restore
1557     // the keyword verbatim score.
1558     { "[\"a\",[\"b\"],[],[],{\"google:suggestrelevance\":[9999],"
1559                             "\"google:verbatimrelevance\":0}]",
1560       { { "b",   true,  false },
1561         { "a",   true,  true },
1562         { "k a", false, false },
1563         kEmptyMatch, kEmptyMatch, kEmptyMatch },
1564       std::string() },
1565     { "[\"a\",[\"http://b.com\"],[],[],"
1566        "{\"google:suggesttype\":[\"NAVIGATION\"],"
1567         "\"google:suggestrelevance\":[9999],"
1568         "\"google:verbatimrelevance\":0}]",
1569       { { "b.com", false, false },
1570         { "a",     true,  true },
1571         { "k a",   false, false },
1572         kEmptyMatch, kEmptyMatch, kEmptyMatch },
1573       std::string() },
1574
1575     // The top result does not have to score as highly as calculated
1576     // verbatim.  i.e., there are no minimum score restrictions in
1577     // this provider.
1578     { "[\"a\",[\"a1\"],[],[],{\"google:verbatimrelevance\":0}]",
1579       { { "a1",  true,  true },
1580         { "k a", false, false },
1581         kEmptyMatch, kEmptyMatch, kEmptyMatch, kEmptyMatch },
1582       "1" },
1583     { "[\"a\",[\"a1\"],[],[],{\"google:verbatimrelevance\":1}]",
1584       { { "a1",  true,  true },
1585         { "k a", false, false },
1586         { "a",   true,  true },
1587         kEmptyMatch, kEmptyMatch, kEmptyMatch },
1588       "1" },
1589     { "[\"a\",[\"a1\"],[],[],{\"google:suggestrelevance\":[1],"
1590                              "\"google:verbatimrelevance\":0}]",
1591       { { "k a", false, false },
1592         { "a1",   true, true },
1593         kEmptyMatch, kEmptyMatch, kEmptyMatch, kEmptyMatch },
1594       "1" },
1595     { "[\"a\",[\"a1\", \"a2\"],[],[],{\"google:suggestrelevance\":[1, 2],"
1596                                      "\"google:verbatimrelevance\":0}]",
1597       {
1598         { "k a", false, false },
1599         { "a2",  true,  true },
1600         { "a1",  true,  true },
1601         kEmptyMatch, kEmptyMatch, kEmptyMatch },
1602       "2" },
1603     { "[\"a\",[\"a1\", \"a2\"],[],[],{\"google:suggestrelevance\":[1, 3],"
1604       "\"google:verbatimrelevance\":2}]",
1605       { { "k a", false, false },
1606         { "a2",  true,  true },
1607         { "a",   true,  true },
1608         { "a1",  true,  true },
1609         kEmptyMatch, kEmptyMatch },
1610       "2" },
1611
1612     // Ensure that all suggestions are considered, regardless of order.
1613     { "[\"a\",[\"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"],[],[],"
1614        "{\"google:suggestrelevance\":[1, 2, 3, 4, 5, 6, 7]}]",
1615       { { "a",   true,  true },
1616         { "k a", false, false },
1617         { "h",   true,  false },
1618         { "g",   true,  false },
1619         { "f",   true,  false },
1620         { "e",   true,  false } },
1621       std::string() },
1622     { "[\"a\",[\"http://b.com\", \"http://c.com\", \"http://d.com\","
1623               "\"http://e.com\", \"http://f.com\", \"http://g.com\","
1624               "\"http://h.com\"],[],[],"
1625        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\","
1626                                 "\"NAVIGATION\", \"NAVIGATION\","
1627                                 "\"NAVIGATION\", \"NAVIGATION\","
1628                                 "\"NAVIGATION\"],"
1629         "\"google:suggestrelevance\":[1, 2, 3, 4, 5, 6, 7]}]",
1630       { { "a",     true,  true },
1631         { "k a",   false, false },
1632         { "h.com", false, false },
1633         { "g.com", false, false },
1634         { "f.com", false, false },
1635         { "e.com", false, false } },
1636       std::string() },
1637
1638     // Ensure that incorrectly sized suggestion relevance lists are ignored.
1639     // Note that keyword suggestions by default (not in suggested relevance
1640     // mode) score more highly than the default verbatim.
1641     { "[\"a\",[\"a1\", \"a2\"],[],[],{\"google:suggestrelevance\":[1]}]",
1642       { { "a",   true,  true },
1643         { "a1",  true,  true },
1644         { "a2",  true,  true },
1645         { "k a", false, false },
1646         kEmptyMatch, kEmptyMatch },
1647       std::string() },
1648     { "[\"a\",[\"a1\"],[],[],{\"google:suggestrelevance\":[9999, 1]}]",
1649       { { "a",   true,  true },
1650         { "a1",  true,  true },
1651         { "k a", false, false },
1652         kEmptyMatch, kEmptyMatch, kEmptyMatch },
1653       std::string() },
1654     // In this case, ignoring the suggested relevance scores means we keep
1655     // only one navsuggest result.
1656     { "[\"a\",[\"http://a1.com\", \"http://a2.com\"],[],[],"
1657        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\"],"
1658         "\"google:suggestrelevance\":[1]}]",
1659       { { "a",      true,  true },
1660         { "a1.com", false, false },
1661         { "k a",    false, false },
1662         kEmptyMatch, kEmptyMatch, kEmptyMatch },
1663       std::string() },
1664     { "[\"a\",[\"http://a1.com\"],[],[],"
1665        "{\"google:suggesttype\":[\"NAVIGATION\"],"
1666        "\"google:suggestrelevance\":[9999, 1]}]",
1667       { { "a",      true,  true },
1668         { "a1.com", false, false },
1669         { "k a",    false, false },
1670         kEmptyMatch, kEmptyMatch, kEmptyMatch },
1671       std::string() },
1672
1673     // Ensure that all 'verbatim' results are merged with their maximum score.
1674     { "[\"a\",[\"a\", \"a1\", \"a2\"],[],[],"
1675        "{\"google:suggestrelevance\":[9998, 9997, 9999]}]",
1676       { { "a2",  true,  true },
1677         { "a",   true,  true },
1678         { "a1",  true,  true },
1679         { "k a", false, false },
1680         kEmptyMatch, kEmptyMatch },
1681       "2" },
1682     { "[\"a\",[\"a\", \"a1\", \"a2\"],[],[],"
1683        "{\"google:suggestrelevance\":[9998, 9997, 9999],"
1684         "\"google:verbatimrelevance\":0}]",
1685       { { "a2",  true,  true },
1686         { "a",   true,  true },
1687         { "a1",  true,  true },
1688         { "k a", false, false },
1689         kEmptyMatch, kEmptyMatch },
1690       "2" },
1691
1692     // Ensure that verbatim is always generated without other suggestions.
1693     // TODO(mpearson): Ensure the value of verbatimrelevance is respected
1694     // (except when suggested relevances are ignored).
1695     { "[\"a\",[],[],[],{\"google:verbatimrelevance\":1}]",
1696       { { "k a", false, false },
1697         { "a",   true,  true },
1698         kEmptyMatch, kEmptyMatch, kEmptyMatch, kEmptyMatch },
1699       std::string() },
1700     { "[\"a\",[],[],[],{\"google:verbatimrelevance\":0}]",
1701       { { "a",   true,  true },
1702         { "k a", false, false },
1703         kEmptyMatch, kEmptyMatch, kEmptyMatch, kEmptyMatch },
1704       std::string() },
1705
1706     // In reorder mode, navsuggestions will not need to be demoted (because
1707     // they are marked as not allowed to be default match and will be
1708     // reordered as necessary).
1709     { "[\"a\",[\"http://a1.com\", \"http://a2.com\"],[],[],"
1710        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\"],"
1711         "\"google:verbatimrelevance\":9990,"
1712         "\"google:suggestrelevance\":[9998, 9999]}]",
1713       { { "a2.com", false, false },
1714         { "a1.com", false, false },
1715         { "a",      true,  true },
1716         { "k a",    false, false },
1717         kEmptyMatch, kEmptyMatch },
1718       std::string() },
1719     { "[\"a\",[\"http://a1.com\", \"http://a2.com\"],[],[],"
1720        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\"],"
1721         "\"google:verbatimrelevance\":9990,"
1722         "\"google:suggestrelevance\":[9999, 9998]}]",
1723       { { "a1.com", false, false },
1724         { "a2.com", false, false },
1725         { "a",      true,  true },
1726         { "k a",    false, false },
1727         kEmptyMatch, kEmptyMatch },
1728       std::string() },
1729     { "[\"a\",[\"https://a/\"],[],[],"
1730        "{\"google:suggesttype\":[\"NAVIGATION\"],"
1731         "\"google:suggestrelevance\":[9999]}]",
1732       { { "https://a", false, false },
1733         { "a",         true,  true },
1734         { "k a",       false, false },
1735         kEmptyMatch, kEmptyMatch, kEmptyMatch },
1736       std::string() },
1737     // Check when navsuggest scores more than verbatim and there is query
1738     // suggestion but it scores lower.
1739     { "[\"a\",[\"http://a1.com\", \"http://a2.com\", \"a3\"],[],[],"
1740        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\", \"QUERY\"],"
1741         "\"google:verbatimrelevance\":9990,"
1742         "\"google:suggestrelevance\":[9998, 9999, 1300]}]",
1743       { { "a2.com", false, false },
1744         { "a1.com", false, false },
1745         { "a",      true,  true },
1746         { "a3",     true,  true },
1747         { "k a",    false, false },
1748         kEmptyMatch },
1749       std::string() },
1750     { "[\"a\",[\"http://a1.com\", \"http://a2.com\", \"a3\"],[],[],"
1751        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\", \"QUERY\"],"
1752         "\"google:verbatimrelevance\":9990,"
1753         "\"google:suggestrelevance\":[9999, 9998, 1300]}]",
1754       { { "a1.com", false, false },
1755         { "a2.com", false, false },
1756         { "a",      true,  true },
1757         { "a3",     true,  true },
1758         { "k a",    false, false },
1759         kEmptyMatch },
1760       std::string() },
1761     // Check when navsuggest scores more than a query suggestion.  There is
1762     // a verbatim but it scores lower.
1763     { "[\"a\",[\"http://a1.com\", \"http://a2.com\", \"a3\"],[],[],"
1764        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\", \"QUERY\"],"
1765         "\"google:verbatimrelevance\":9990,"
1766         "\"google:suggestrelevance\":[9998, 9999, 9997]}]",
1767       { { "a2.com", false, false },
1768         { "a1.com", false, false },
1769         { "a3",     true,  true },
1770         { "a",      true,  true },
1771         { "k a",    false, false },
1772         kEmptyMatch },
1773       "3" },
1774     { "[\"a\",[\"http://a1.com\", \"http://a2.com\", \"a3\"],[],[],"
1775        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\", \"QUERY\"],"
1776         "\"google:verbatimrelevance\":9990,"
1777         "\"google:suggestrelevance\":[9999, 9998, 9997]}]",
1778       { { "a1.com", false, false },
1779         { "a2.com", false, false },
1780         { "a3",     true,  true },
1781         { "a",      true,  true },
1782         { "k a",    false, false },
1783         kEmptyMatch },
1784       "3" },
1785     { "[\"a\",[\"http://a1.com\", \"http://a2.com\", \"a3\"],[],[],"
1786        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\", \"QUERY\"],"
1787         "\"google:verbatimrelevance\":0,"
1788         "\"google:suggestrelevance\":[9998, 9999, 9997]}]",
1789       { { "a2.com", false, false },
1790         { "a1.com", false, false },
1791         { "a3",     true,  true },
1792         { "k a",    false, false },
1793         kEmptyMatch, kEmptyMatch },
1794       "3" },
1795     { "[\"a\",[\"http://a1.com\", \"http://a2.com\", \"a3\"],[],[],"
1796        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\", \"QUERY\"],"
1797         "\"google:verbatimrelevance\":0,"
1798         "\"google:suggestrelevance\":[9999, 9998, 9997]}]",
1799       { { "a1.com", false, false },
1800         { "a2.com", false, false },
1801         { "a3",     true,  true },
1802         { "k a",    false, false },
1803         kEmptyMatch, kEmptyMatch },
1804       "3" },
1805     // Check when there is neither verbatim nor a query suggestion that,
1806     // because we can't demote navsuggestions below a query suggestion,
1807     // we restore the keyword verbatim score.
1808     { "[\"a\",[\"http://a1.com\", \"http://a2.com\"],[],[],"
1809        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\"],"
1810         "\"google:verbatimrelevance\":0,"
1811         "\"google:suggestrelevance\":[9998, 9999]}]",
1812       { { "a2.com", false, false },
1813         { "a1.com", false, false },
1814         { "a",      true,  true },
1815         { "k a",    false, false },
1816         kEmptyMatch, kEmptyMatch },
1817       std::string() },
1818     { "[\"a\",[\"http://a1.com\", \"http://a2.com\"],[],[],"
1819        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\"],"
1820         "\"google:verbatimrelevance\":0,"
1821         "\"google:suggestrelevance\":[9999, 9998]}]",
1822       { { "a1.com", false, false },
1823         { "a2.com", false, false },
1824         { "a",      true,  true },
1825         { "k a",    false, false },
1826         kEmptyMatch, kEmptyMatch },
1827       std::string() },
1828     // More checks that everything works when it's not necessary to demote.
1829     { "[\"a\",[\"http://a1.com\", \"http://a2.com\", \"a3\"],[],[],"
1830        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\", \"QUERY\"],"
1831         "\"google:verbatimrelevance\":9990,"
1832         "\"google:suggestrelevance\":[9997, 9998, 9999]}]",
1833       { { "a3",     true,  true },
1834         { "a2.com", false, false },
1835         { "a1.com", false, false },
1836         { "a",      true,  true },
1837         { "k a",    false, false },
1838         kEmptyMatch },
1839       "3" },
1840     { "[\"a\",[\"http://a1.com\", \"http://a2.com\", \"a3\"],[],[],"
1841        "{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\", \"QUERY\"],"
1842         "\"google:verbatimrelevance\":9990,"
1843         "\"google:suggestrelevance\":[9998, 9997, 9999]}]",
1844       { { "a3",     true,  true },
1845         { "a1.com", false, false },
1846         { "a2.com", false, false },
1847         { "a",      true,  true },
1848         { "k a",    false, false },
1849         kEmptyMatch },
1850       "3" },
1851   };
1852
1853   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
1854     QueryForInput(ASCIIToUTF16("k a"), false, true);
1855
1856     // Set up a default fetcher with no results.
1857     net::TestURLFetcher* default_fetcher =
1858         test_factory_.GetFetcherByID(
1859             SearchProvider::kDefaultProviderURLFetcherID);
1860     ASSERT_TRUE(default_fetcher);
1861     default_fetcher->set_response_code(200);
1862     default_fetcher->delegate()->OnURLFetchComplete(default_fetcher);
1863     default_fetcher = NULL;
1864
1865     // Set up a keyword fetcher with provided results.
1866     net::TestURLFetcher* keyword_fetcher =
1867         test_factory_.GetFetcherByID(
1868             SearchProvider::kKeywordProviderURLFetcherID);
1869     ASSERT_TRUE(keyword_fetcher);
1870     keyword_fetcher->set_response_code(200);
1871     keyword_fetcher->SetResponseString(cases[i].json);
1872     keyword_fetcher->delegate()->OnURLFetchComplete(keyword_fetcher);
1873     keyword_fetcher = NULL;
1874     RunTillProviderDone();
1875
1876     const std::string description = "for input with json=" + cases[i].json;
1877     const ACMatches& matches = provider_->matches();
1878     ASSERT_FALSE(matches.empty());
1879     // Find the first match that's allowed to be the default match and check
1880     // its inline_autocompletion.
1881     ACMatches::const_iterator it = FindDefaultMatch(matches);
1882     ASSERT_NE(matches.end(), it);
1883     EXPECT_EQ(ASCIIToUTF16(cases[i].inline_autocompletion),
1884               it->inline_autocompletion) << description;
1885
1886     ASSERT_LE(matches.size(), ARRAYSIZE_UNSAFE(cases[i].matches));
1887     size_t j = 0;
1888     // Ensure that the returned matches equal the expectations.
1889     for (; j < matches.size(); ++j) {
1890       EXPECT_EQ(ASCIIToUTF16(cases[i].matches[j].contents),
1891                 matches[j].contents) << description;
1892       EXPECT_EQ(cases[i].matches[j].from_keyword,
1893                 matches[j].keyword == ASCIIToUTF16("k")) << description;
1894       EXPECT_EQ(cases[i].matches[j].allowed_to_be_default_match,
1895                 matches[j].allowed_to_be_default_match) << description;
1896     }
1897     // Ensure that no expected matches are missing.
1898     for (; j < ARRAYSIZE_UNSAFE(cases[i].matches); ++j)
1899       EXPECT_EQ(kNotApplicable, cases[i].matches[j].contents) <<
1900           "Case # " << i << " " << description;
1901   }
1902 }
1903
1904 TEST_F(SearchProviderTest, LocalAndRemoteRelevances) {
1905   // We hardcode the string "term1" below, so ensure that the search term that
1906   // got added to history already is that string.
1907   ASSERT_EQ(ASCIIToUTF16("term1"), term1_);
1908   base::string16 term = term1_.substr(0, term1_.length() - 1);
1909
1910   AddSearchToHistory(default_t_url_, term + ASCIIToUTF16("2"), 2);
1911   profile_.BlockUntilHistoryProcessesPendingRequests();
1912
1913   struct {
1914     const base::string16 input;
1915     const std::string json;
1916     const std::string matches[6];
1917   } cases[] = {
1918     // The history results outscore the default verbatim score.  term2 has more
1919     // visits so it outscores term1.  The suggestions are still returned since
1920     // they're server-scored.
1921     { term,
1922       "[\"term\",[\"a1\", \"a2\", \"a3\"],[],[],"
1923        "{\"google:suggesttype\":[\"QUERY\", \"QUERY\", \"QUERY\"],"
1924         "\"google:suggestrelevance\":[1, 2, 3]}]",
1925       { "term2", "term1", "term", "a3", "a2", "a1" } },
1926     // Because we already have three suggestions by the time we see the history
1927     // results, they don't get returned.
1928     { term,
1929       "[\"term\",[\"a1\", \"a2\", \"a3\"],[],[],"
1930        "{\"google:suggesttype\":[\"QUERY\", \"QUERY\", \"QUERY\"],"
1931         "\"google:verbatimrelevance\":1450,"
1932         "\"google:suggestrelevance\":[1440, 1430, 1420]}]",
1933       { "term", "a1", "a2", "a3", kNotApplicable, kNotApplicable } },
1934     // If we only have two suggestions, we have room for a history result.
1935     { term,
1936       "[\"term\",[\"a1\", \"a2\"],[],[],"
1937        "{\"google:suggesttype\":[\"QUERY\", \"QUERY\"],"
1938         "\"google:verbatimrelevance\":1450,"
1939         "\"google:suggestrelevance\":[1430, 1410]}]",
1940       { "term", "a1", "a2", "term2", kNotApplicable, kNotApplicable } },
1941     // If we have more than three suggestions, they should all be returned as
1942     // long as we have enough total space for them.
1943     { term,
1944       "[\"term\",[\"a1\", \"a2\", \"a3\", \"a4\"],[],[],"
1945        "{\"google:suggesttype\":[\"QUERY\", \"QUERY\", \"QUERY\", \"QUERY\"],"
1946         "\"google:verbatimrelevance\":1450,"
1947         "\"google:suggestrelevance\":[1440, 1430, 1420, 1410]}]",
1948       { "term", "a1", "a2", "a3", "a4", kNotApplicable } },
1949     { term,
1950       "[\"term\",[\"a1\", \"a2\", \"a3\", \"a4\", \"a5\", \"a6\"],[],[],"
1951        "{\"google:suggesttype\":[\"QUERY\", \"QUERY\", \"QUERY\", \"QUERY\","
1952                                 "\"QUERY\", \"QUERY\"],"
1953         "\"google:verbatimrelevance\":1450,"
1954         "\"google:suggestrelevance\":[1440, 1430, 1420, 1410, 1400, 1390]}]",
1955       { "term", "a1", "a2", "a3", "a4", "a5" } },
1956     { term,
1957       "[\"term\",[\"a1\", \"a2\", \"a3\", \"a4\"],[],[],"
1958        "{\"google:suggesttype\":[\"QUERY\", \"QUERY\", \"QUERY\", \"QUERY\"],"
1959         "\"google:verbatimrelevance\":1450,"
1960         "\"google:suggestrelevance\":[1430, 1410, 1390, 1370]}]",
1961       { "term", "a1", "a2", "term2", "a3", "a4" } }
1962   };
1963
1964   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
1965     QueryForInput(cases[i].input, false, false);
1966     net::TestURLFetcher* fetcher =
1967         test_factory_.GetFetcherByID(
1968             SearchProvider::kDefaultProviderURLFetcherID);
1969     ASSERT_TRUE(fetcher);
1970     fetcher->set_response_code(200);
1971     fetcher->SetResponseString(cases[i].json);
1972     fetcher->delegate()->OnURLFetchComplete(fetcher);
1973     RunTillProviderDone();
1974
1975     const std::string description = "for input with json=" + cases[i].json;
1976     const ACMatches& matches = provider_->matches();
1977
1978     // Ensure no extra matches are present.
1979     ASSERT_LE(matches.size(), ARRAYSIZE_UNSAFE(cases[i].matches));
1980
1981     size_t j = 0;
1982     // Ensure that the returned matches equal the expectations.
1983     for (; j < matches.size(); ++j)
1984       EXPECT_EQ(ASCIIToUTF16(cases[i].matches[j]),
1985                 matches[j].contents) << description;
1986     // Ensure that no expected matches are missing.
1987     for (; j < ARRAYSIZE_UNSAFE(cases[i].matches); ++j)
1988       EXPECT_EQ(kNotApplicable, cases[i].matches[j]) <<
1989           "Case # " << i << " " << description;
1990   }
1991 }
1992
1993 // Verifies suggest relevance behavior for URL input.
1994 TEST_F(SearchProviderTest, DefaultProviderSuggestRelevanceScoringUrlInput) {
1995   struct DefaultFetcherUrlInputMatch {
1996     const std::string match_contents;
1997     AutocompleteMatch::Type match_type;
1998     bool allowed_to_be_default_match;
1999   };
2000   const DefaultFetcherUrlInputMatch kEmptyMatch =
2001       { kNotApplicable, AutocompleteMatchType::NUM_TYPES, false };
2002   struct {
2003     const std::string input;
2004     const std::string json;
2005     const DefaultFetcherUrlInputMatch output[4];
2006   } cases[] = {
2007     // Ensure NAVIGATION matches are allowed to be listed first for URL
2008     // input regardless of whether the match is inlineable.  Note that
2009     // non-inlineable matches should not be allowed to be the default match.
2010     { "a.com", "[\"a.com\",[\"http://b.com/\"],[],[],"
2011                 "{\"google:suggesttype\":[\"NAVIGATION\"],"
2012                  "\"google:suggestrelevance\":[9999]}]",
2013       { { "b.com",   AutocompleteMatchType::NAVSUGGEST,            false },
2014         { "a.com",   AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, true },
2015         kEmptyMatch, kEmptyMatch } },
2016     { "a.com", "[\"a.com\",[\"https://b.com\"],[],[],"
2017                 "{\"google:suggesttype\":[\"NAVIGATION\"],"
2018                  "\"google:suggestrelevance\":[9999]}]",
2019       { { "https://b.com", AutocompleteMatchType::NAVSUGGEST,           false },
2020         { "a.com",         AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, true },
2021         kEmptyMatch, kEmptyMatch } },
2022     { "a.com", "[\"a.com\",[\"http://a.com/a\"],[],[],"
2023                 "{\"google:suggesttype\":[\"NAVIGATION\"],"
2024                  "\"google:suggestrelevance\":[9999]}]",
2025       { { "a.com/a", AutocompleteMatchType::NAVSUGGEST,            true },
2026         { "a.com",   AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, true },
2027         kEmptyMatch, kEmptyMatch } },
2028     { "a.com", "[\"a.com\",[\"https://a.com\"],[],[],"
2029                 "{\"google:suggesttype\":[\"NAVIGATION\"],"
2030                  "\"google:suggestrelevance\":[9999]}]",
2031       { { "https://a.com", AutocompleteMatchType::NAVSUGGEST,            true },
2032         { "a.com",         AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, true },
2033         kEmptyMatch, kEmptyMatch } },
2034
2035     // Ensure topmost inlineable SUGGEST matches are NOT allowed for URL
2036     // input.  SearchProvider disregards search and verbatim suggested
2037     // relevances.
2038     { "a.com", "[\"a.com\",[\"a.com info\"],[],[],"
2039                 "{\"google:suggestrelevance\":[9999]}]",
2040       { { "a.com",      AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, true },
2041         { "a.com info", AutocompleteMatchType::SEARCH_SUGGEST,        true },
2042         kEmptyMatch, kEmptyMatch } },
2043     { "a.com", "[\"a.com\",[\"a.com info\"],[],[],"
2044                 "{\"google:suggestrelevance\":[9999]}]",
2045       { { "a.com",   AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,   true },
2046         { "a.com info", AutocompleteMatchType::SEARCH_SUGGEST,        true },
2047         kEmptyMatch, kEmptyMatch } },
2048
2049     // Ensure the fallback mechanism allows inlinable NAVIGATION matches.
2050     { "a.com", "[\"a.com\",[\"a.com info\", \"http://a.com/b\"],[],[],"
2051                 "{\"google:suggesttype\":[\"QUERY\", \"NAVIGATION\"],"
2052                  "\"google:suggestrelevance\":[9999, 9998]}]",
2053       { { "a.com/b",    AutocompleteMatchType::NAVSUGGEST,            true },
2054         { "a.com",      AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, true },
2055         { "a.com info", AutocompleteMatchType::SEARCH_SUGGEST,        true },
2056         kEmptyMatch } },
2057     { "a.com", "[\"a.com\",[\"a.com info\", \"http://a.com/b\"],[],[],"
2058                 "{\"google:suggesttype\":[\"QUERY\", \"NAVIGATION\"],"
2059                  "\"google:suggestrelevance\":[9998, 9997],"
2060                  "\"google:verbatimrelevance\":9999}]",
2061       { { "a.com/b",    AutocompleteMatchType::NAVSUGGEST,            true },
2062         { "a.com",      AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, true },
2063         { "a.com info", AutocompleteMatchType::SEARCH_SUGGEST,        true },
2064         kEmptyMatch } },
2065
2066     // Ensure topmost non-inlineable SUGGEST matches are allowed for URL
2067     // input assuming the top inlineable match is not a query (i.e., is a
2068     // NAVSUGGEST).
2069     { "a.com", "[\"a.com\",[\"info\"],[],[],"
2070                 "{\"google:suggestrelevance\":[9999]}]",
2071       { { "info",  AutocompleteMatchType::SEARCH_SUGGEST,        false },
2072         { "a.com", AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, true },
2073         kEmptyMatch, kEmptyMatch } },
2074     { "a.com", "[\"a.com\",[\"info\"],[],[],"
2075                 "{\"google:suggestrelevance\":[9999]}]",
2076       { { "info",  AutocompleteMatchType::SEARCH_SUGGEST,        false },
2077         { "a.com", AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, true },
2078         kEmptyMatch, kEmptyMatch } },
2079   };
2080
2081   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
2082     QueryForInput(ASCIIToUTF16(cases[i].input), false, false);
2083     net::TestURLFetcher* fetcher =
2084         test_factory_.GetFetcherByID(
2085             SearchProvider::kDefaultProviderURLFetcherID);
2086     ASSERT_TRUE(fetcher);
2087     fetcher->set_response_code(200);
2088     fetcher->SetResponseString(cases[i].json);
2089     fetcher->delegate()->OnURLFetchComplete(fetcher);
2090     RunTillProviderDone();
2091
2092     size_t j = 0;
2093     const ACMatches& matches = provider_->matches();
2094     ASSERT_LE(matches.size(), ARRAYSIZE_UNSAFE(cases[i].output));
2095     // Ensure that the returned matches equal the expectations.
2096     for (; j < matches.size(); ++j) {
2097       EXPECT_EQ(ASCIIToUTF16(cases[i].output[j].match_contents),
2098                 matches[j].contents);
2099       EXPECT_EQ(cases[i].output[j].match_type, matches[j].type);
2100       EXPECT_EQ(cases[i].output[j].allowed_to_be_default_match,
2101                 matches[j].allowed_to_be_default_match);
2102     }
2103     // Ensure that no expected matches are missing.
2104     for (; j < ARRAYSIZE_UNSAFE(cases[i].output); ++j) {
2105       EXPECT_EQ(kNotApplicable, cases[i].output[j].match_contents);
2106       EXPECT_EQ(AutocompleteMatchType::NUM_TYPES,
2107                 cases[i].output[j].match_type);
2108       EXPECT_FALSE(cases[i].output[j].allowed_to_be_default_match);
2109     }
2110   }
2111 }
2112
2113 // A basic test that verifies the field trial triggered parsing logic.
2114 TEST_F(SearchProviderTest, FieldTrialTriggeredParsing) {
2115   QueryForInput(ASCIIToUTF16("foo"), false, false);
2116
2117   // Make sure the default providers suggest service was queried.
2118   net::TestURLFetcher* fetcher = test_factory_.GetFetcherByID(
2119       SearchProvider::kDefaultProviderURLFetcherID);
2120   ASSERT_TRUE(fetcher);
2121
2122   // Tell the SearchProvider the suggest query is done.
2123   fetcher->set_response_code(200);
2124   fetcher->SetResponseString(
2125       "[\"foo\",[\"foo bar\"],[\"\"],[],"
2126       "{\"google:suggesttype\":[\"QUERY\"],"
2127       "\"google:fieldtrialtriggered\":true}]");
2128   fetcher->delegate()->OnURLFetchComplete(fetcher);
2129   fetcher = NULL;
2130
2131   // Run till the history results complete.
2132   RunTillProviderDone();
2133
2134   {
2135     // Check for the match and field trial triggered bits.
2136     AutocompleteMatch match;
2137     EXPECT_TRUE(FindMatchWithContents(ASCIIToUTF16("foo bar"), &match));
2138     ProvidersInfo providers_info;
2139     provider_->AddProviderInfo(&providers_info);
2140     ASSERT_EQ(1U, providers_info.size());
2141     EXPECT_EQ(1, providers_info[0].field_trial_triggered_size());
2142     EXPECT_EQ(1, providers_info[0].field_trial_triggered_in_session_size());
2143   }
2144   {
2145     // Reset the session and check that bits are reset.
2146     provider_->ResetSession();
2147     ProvidersInfo providers_info;
2148     provider_->AddProviderInfo(&providers_info);
2149     ASSERT_EQ(1U, providers_info.size());
2150     EXPECT_EQ(1, providers_info[0].field_trial_triggered_size());
2151     EXPECT_EQ(0, providers_info[0].field_trial_triggered_in_session_size());
2152   }
2153 }
2154
2155 // Verifies inline autocompletion of navigational results.
2156 TEST_F(SearchProviderTest, NavigationInline) {
2157   struct {
2158     const std::string input;
2159     const std::string url;
2160     // Test the expected fill_into_edit, which may drop "http://".
2161     // Some cases do not trim "http://" to match from the start of the scheme.
2162     const std::string fill_into_edit;
2163     const std::string inline_autocompletion;
2164     const bool allowed_to_be_default_match_in_regular_mode;
2165     const bool allowed_to_be_default_match_in_prevent_inline_mode;
2166   } cases[] = {
2167     // Do not inline matches that do not contain the input; trim http as needed.
2168     { "x",                 "http://www.abc.com",
2169                                   "www.abc.com",  std::string(), false, false },
2170     { "https:",            "http://www.abc.com",
2171                                   "www.abc.com",  std::string(), false, false },
2172     { "http://www.abc.com/a", "http://www.abc.com",
2173                               "http://www.abc.com",  std::string(), false,
2174                                                                     false },
2175     { "http://www.abc.com",   "https://www.abc.com",
2176                               "https://www.abc.com", std::string(), false,
2177                                                                     false },
2178     { "http://abc.com",       "ftp://abc.com",
2179                               "ftp://abc.com",       std::string(), false,
2180                                                                     false },
2181     { "https://www.abc.com",  "http://www.abc.com",
2182                                      "www.abc.com",  std::string(), false,
2183                                                                     false },
2184     { "ftp://abc.com",        "http://abc.com",
2185                                      "abc.com",      std::string(), false,
2186                                                                     false },
2187
2188     // Do not inline matches with invalid input prefixes; trim http as needed.
2189     { "ttp",              "http://www.abc.com",
2190                                  "www.abc.com", std::string(), false, false },
2191     { "://w",             "http://www.abc.com",
2192                                  "www.abc.com", std::string(), false, false },
2193     { "ww.",              "http://www.abc.com",
2194                                  "www.abc.com", std::string(), false, false },
2195     { ".ab",              "http://www.abc.com",
2196                                  "www.abc.com", std::string(), false, false },
2197     { "bc",               "http://www.abc.com",
2198                                  "www.abc.com", std::string(), false, false },
2199     { ".com",             "http://www.abc.com",
2200                                  "www.abc.com", std::string(), false, false },
2201
2202     // Do not inline matches that omit input domain labels; trim http as needed.
2203     { "www.a",            "http://a.com",
2204                                  "a.com",       std::string(), false, false },
2205     { "http://www.a",     "http://a.com",
2206                           "http://a.com",       std::string(), false, false },
2207     { "www.a",            "ftp://a.com",
2208                           "ftp://a.com",        std::string(), false, false },
2209     { "ftp://www.a",      "ftp://a.com",
2210                           "ftp://a.com",        std::string(), false, false },
2211
2212     // Input matching but with nothing to inline will not yield an offset, but
2213     // will be allowed to be default.
2214     { "abc.com",             "http://www.abc.com",
2215                                     "www.abc.com", std::string(), true, true },
2216     { "abc.com/",            "http://www.abc.com",
2217                                     "www.abc.com", std::string(), true, true },
2218     { "http://www.abc.com",  "http://www.abc.com",
2219                              "http://www.abc.com", std::string(), true, true },
2220     { "http://www.abc.com/", "http://www.abc.com",
2221                              "http://www.abc.com", std::string(), true, true },
2222
2223     // Inputs with trailing whitespace should inline when possible.
2224     { "abc.com ",      "http://www.abc.com",
2225                               "www.abc.com",      std::string(), true,  true },
2226     { "abc.com/ ",     "http://www.abc.com",
2227                               "www.abc.com",      std::string(), true,  true },
2228     { "abc.com ",      "http://www.abc.com/bar",
2229                               "www.abc.com/bar",  "/bar",        false, false },
2230
2231     // Inline matches when the input is a leading substring of the scheme.
2232     { "h",             "http://www.abc.com",
2233                        "http://www.abc.com", "ttp://www.abc.com", true, false },
2234     { "http",          "http://www.abc.com",
2235                        "http://www.abc.com", "://www.abc.com",    true, false },
2236
2237     // Inline matches when the input is a leading substring of the full URL.
2238     { "http:",             "http://www.abc.com",
2239                            "http://www.abc.com", "//www.abc.com", true, false },
2240     { "http://w",          "http://www.abc.com",
2241                            "http://www.abc.com", "ww.abc.com",    true, false },
2242     { "http://www.",       "http://www.abc.com",
2243                            "http://www.abc.com", "abc.com",       true, false },
2244     { "http://www.ab",     "http://www.abc.com",
2245                            "http://www.abc.com", "c.com",         true, false },
2246     { "http://www.abc.com/p", "http://www.abc.com/path/file.htm?q=x#foo",
2247                               "http://www.abc.com/path/file.htm?q=x#foo",
2248                                                   "ath/file.htm?q=x#foo",
2249                                                                   true, false },
2250     { "http://abc.com/p",     "http://abc.com/path/file.htm?q=x#foo",
2251                               "http://abc.com/path/file.htm?q=x#foo",
2252                                               "ath/file.htm?q=x#foo",
2253                                                                   true, false},
2254
2255     // Inline matches with valid URLPrefixes; only trim "http://".
2256     { "w",               "http://www.abc.com",
2257                                 "www.abc.com", "ww.abc.com", true, false },
2258     { "www.a",           "http://www.abc.com",
2259                                 "www.abc.com", "bc.com",     true, false },
2260     { "abc",             "http://www.abc.com",
2261                                 "www.abc.com", ".com",       true, false },
2262     { "abc.c",           "http://www.abc.com",
2263                                 "www.abc.com", "om",         true, false },
2264     { "abc.com/p",       "http://www.abc.com/path/file.htm?q=x#foo",
2265                                 "www.abc.com/path/file.htm?q=x#foo",
2266                                              "ath/file.htm?q=x#foo",
2267                                                              true, false },
2268     { "abc.com/p",       "http://abc.com/path/file.htm?q=x#foo",
2269                                 "abc.com/path/file.htm?q=x#foo",
2270                                          "ath/file.htm?q=x#foo",
2271                                                              true, false },
2272
2273     // Inline matches using the maximal URLPrefix components.
2274     { "h",               "http://help.com",
2275                                 "help.com", "elp.com",     true, false },
2276     { "http",            "http://http.com",
2277                                 "http.com", ".com",        true, false },
2278     { "h",               "http://www.help.com",
2279                                 "www.help.com", "elp.com", true, false },
2280     { "http",            "http://www.http.com",
2281                                 "www.http.com", ".com",    true, false },
2282     { "w",               "http://www.www.com",
2283                                 "www.www.com",  "ww.com",  true, false },
2284
2285     // Test similar behavior for the ftp and https schemes.
2286     { "ftp://www.ab",  "ftp://www.abc.com/path/file.htm?q=x#foo",
2287                        "ftp://www.abc.com/path/file.htm?q=x#foo",
2288                                   "c.com/path/file.htm?q=x#foo",  true, false },
2289     { "www.ab",        "ftp://www.abc.com/path/file.htm?q=x#foo",
2290                        "ftp://www.abc.com/path/file.htm?q=x#foo",
2291                                    "c.com/path/file.htm?q=x#foo", true, false },
2292     { "ab",            "ftp://www.abc.com/path/file.htm?q=x#foo",
2293                        "ftp://www.abc.com/path/file.htm?q=x#foo",
2294                                    "c.com/path/file.htm?q=x#foo", true, false },
2295     { "ab",            "ftp://abc.com/path/file.htm?q=x#foo",
2296                        "ftp://abc.com/path/file.htm?q=x#foo",
2297                                "c.com/path/file.htm?q=x#foo",     true, false },
2298     { "https://www.ab",  "https://www.abc.com/path/file.htm?q=x#foo",
2299                          "https://www.abc.com/path/file.htm?q=x#foo",
2300                                        "c.com/path/file.htm?q=x#foo",
2301                                                                   true, false },
2302     { "www.ab",      "https://www.abc.com/path/file.htm?q=x#foo",
2303                      "https://www.abc.com/path/file.htm?q=x#foo",
2304                                    "c.com/path/file.htm?q=x#foo", true, false },
2305     { "ab",          "https://www.abc.com/path/file.htm?q=x#foo",
2306                      "https://www.abc.com/path/file.htm?q=x#foo",
2307                                    "c.com/path/file.htm?q=x#foo", true, false },
2308     { "ab",          "https://abc.com/path/file.htm?q=x#foo",
2309                      "https://abc.com/path/file.htm?q=x#foo",
2310                                "c.com/path/file.htm?q=x#foo",     true, false },
2311
2312     // Forced query input should inline and retain the "?" prefix.
2313     { "?http://www.ab",  "http://www.abc.com",
2314                         "?http://www.abc.com", "c.com", true, false },
2315     { "?www.ab",         "http://www.abc.com",
2316                                "?www.abc.com", "c.com", true, false },
2317     { "?ab",             "http://www.abc.com",
2318                                "?www.abc.com", "c.com", true, false },
2319     { "?abc.com",        "http://www.abc.com",
2320                                "?www.abc.com", "",      true, true },
2321   };
2322
2323   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
2324     // First test regular mode.
2325     QueryForInput(ASCIIToUTF16(cases[i].input), false, false);
2326     AutocompleteMatch match(
2327         provider_->NavigationToMatch(SearchProvider::NavigationResult(
2328             *provider_.get(), GURL(cases[i].url),
2329             AutocompleteMatchType::NAVSUGGEST, base::string16(), std::string(),
2330             false, 0, false, ASCIIToUTF16(cases[i].input), std::string())));
2331     EXPECT_EQ(ASCIIToUTF16(cases[i].inline_autocompletion),
2332               match.inline_autocompletion);
2333     EXPECT_EQ(ASCIIToUTF16(cases[i].fill_into_edit), match.fill_into_edit);
2334     EXPECT_EQ(cases[i].allowed_to_be_default_match_in_regular_mode,
2335               match.allowed_to_be_default_match);
2336
2337     // Then test prevent-inline-autocomplete mode.
2338     QueryForInput(ASCIIToUTF16(cases[i].input), true, false);
2339     AutocompleteMatch match_prevent_inline(
2340         provider_->NavigationToMatch(SearchProvider::NavigationResult(
2341             *provider_.get(), GURL(cases[i].url),
2342             AutocompleteMatchType::NAVSUGGEST, base::string16(), std::string(),
2343             false, 0, false, ASCIIToUTF16(cases[i].input), std::string())));
2344     EXPECT_EQ(ASCIIToUTF16(cases[i].inline_autocompletion),
2345               match_prevent_inline.inline_autocompletion);
2346     EXPECT_EQ(ASCIIToUTF16(cases[i].fill_into_edit),
2347               match_prevent_inline.fill_into_edit);
2348     EXPECT_EQ(cases[i].allowed_to_be_default_match_in_prevent_inline_mode,
2349               match_prevent_inline.allowed_to_be_default_match);
2350   }
2351 }
2352
2353 // Verifies that "http://" is not trimmed for input that is a leading substring.
2354 TEST_F(SearchProviderTest, NavigationInlineSchemeSubstring) {
2355   const base::string16 input(ASCIIToUTF16("ht"));
2356   const base::string16 url(ASCIIToUTF16("http://a.com"));
2357   const SearchProvider::NavigationResult result(
2358       *provider_.get(), GURL(url), AutocompleteMatchType::NAVSUGGEST,
2359       base::string16(), std::string(), false, 0, false, input, std::string());
2360
2361   // Check the offset and strings when inline autocompletion is allowed.
2362   QueryForInput(input, false, false);
2363   AutocompleteMatch match_inline(provider_->NavigationToMatch(result));
2364   EXPECT_EQ(url, match_inline.fill_into_edit);
2365   EXPECT_EQ(url.substr(2), match_inline.inline_autocompletion);
2366   EXPECT_TRUE(match_inline.allowed_to_be_default_match);
2367   EXPECT_EQ(url, match_inline.contents);
2368
2369   // Check the same strings when inline autocompletion is prevented.
2370   QueryForInput(input, true, false);
2371   AutocompleteMatch match_prevent(provider_->NavigationToMatch(result));
2372   EXPECT_EQ(url, match_prevent.fill_into_edit);
2373   EXPECT_FALSE(match_prevent.allowed_to_be_default_match);
2374   EXPECT_EQ(url, match_prevent.contents);
2375 }
2376
2377 // Verifies that input "w" marks a more significant domain label than "www.".
2378 TEST_F(SearchProviderTest, NavigationInlineDomainClassify) {
2379   QueryForInput(ASCIIToUTF16("w"), false, false);
2380   AutocompleteMatch match(
2381       provider_->NavigationToMatch(SearchProvider::NavigationResult(
2382           *provider_.get(), GURL("http://www.wow.com"),
2383           AutocompleteMatchType::NAVSUGGEST, base::string16(), std::string(),
2384           false, 0, false, ASCIIToUTF16("w"), std::string())));
2385   EXPECT_EQ(ASCIIToUTF16("ow.com"), match.inline_autocompletion);
2386   EXPECT_TRUE(match.allowed_to_be_default_match);
2387   EXPECT_EQ(ASCIIToUTF16("www.wow.com"), match.fill_into_edit);
2388   EXPECT_EQ(ASCIIToUTF16("www.wow.com"), match.contents);
2389
2390   // Ensure that the match for input "w" is marked on "wow" and not "www".
2391   ASSERT_EQ(3U, match.contents_class.size());
2392   EXPECT_EQ(0U, match.contents_class[0].offset);
2393   EXPECT_EQ(AutocompleteMatch::ACMatchClassification::URL,
2394             match.contents_class[0].style);
2395   EXPECT_EQ(4U, match.contents_class[1].offset);
2396   EXPECT_EQ(AutocompleteMatch::ACMatchClassification::URL |
2397             AutocompleteMatch::ACMatchClassification::MATCH,
2398             match.contents_class[1].style);
2399   EXPECT_EQ(5U, match.contents_class[2].offset);
2400   EXPECT_EQ(AutocompleteMatch::ACMatchClassification::URL,
2401             match.contents_class[2].style);
2402 }
2403
2404 #if !defined(OS_WIN)
2405 // Verify entity suggestion parsing.
2406 TEST_F(SearchProviderTest, ParseEntitySuggestion) {
2407   struct Match {
2408     std::string contents;
2409     std::string description;
2410     std::string query_params;
2411     std::string fill_into_edit;
2412     AutocompleteMatchType::Type type;
2413   };
2414   const Match kEmptyMatch = {
2415     kNotApplicable, kNotApplicable, kNotApplicable, kNotApplicable,
2416     AutocompleteMatchType::NUM_TYPES};
2417
2418   struct {
2419     const std::string input_text;
2420     const std::string response_json;
2421     const Match matches[5];
2422   } cases[] = {
2423     // A query and an entity suggestion with different search terms.
2424     { "x",
2425       "[\"x\",[\"xy\", \"yy\"],[\"\",\"\"],[],"
2426       " {\"google:suggestdetail\":[{},"
2427       "   {\"a\":\"A\",\"t\":\"xy\",\"q\":\"p=v\"}],"
2428       "\"google:suggesttype\":[\"QUERY\",\"ENTITY\"]}]",
2429       { { "x", "", "", "x", AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED },
2430         { "xy", "", "", "xy", AutocompleteMatchType::SEARCH_SUGGEST },
2431         { "xy", "A", "p=v", "yy",
2432           AutocompleteMatchType::SEARCH_SUGGEST_ENTITY },
2433         kEmptyMatch,
2434         kEmptyMatch
2435       },
2436     },
2437     // A query and an entity suggestion with same search terms.
2438     { "x",
2439       "[\"x\",[\"xy\", \"xy\"],[\"\",\"\"],[],"
2440       " {\"google:suggestdetail\":[{},"
2441       "   {\"a\":\"A\",\"t\":\"xy\",\"q\":\"p=v\"}],"
2442       "\"google:suggesttype\":[\"QUERY\",\"ENTITY\"]}]",
2443       { { "x", "", "", "x", AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED },
2444         { "xy", "", "", "xy", AutocompleteMatchType::SEARCH_SUGGEST },
2445         { "xy", "A", "p=v", "xy",
2446           AutocompleteMatchType::SEARCH_SUGGEST_ENTITY },
2447         kEmptyMatch,
2448         kEmptyMatch
2449       },
2450     },
2451   };
2452   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
2453     QueryForInput(ASCIIToUTF16(cases[i].input_text), false, false);
2454
2455     // Set up a default fetcher with provided results.
2456     net::TestURLFetcher* fetcher =
2457         test_factory_.GetFetcherByID(
2458             SearchProvider::kDefaultProviderURLFetcherID);
2459     ASSERT_TRUE(fetcher);
2460     fetcher->set_response_code(200);
2461     fetcher->SetResponseString(cases[i].response_json);
2462     fetcher->delegate()->OnURLFetchComplete(fetcher);
2463
2464     RunTillProviderDone();
2465
2466     const ACMatches& matches = provider_->matches();
2467     ASSERT_FALSE(matches.empty());
2468
2469     SCOPED_TRACE("for input with json = " + cases[i].response_json);
2470
2471     ASSERT_LE(matches.size(), ARRAYSIZE_UNSAFE(cases[i].matches));
2472     size_t j = 0;
2473     // Ensure that the returned matches equal the expectations.
2474     for (; j < matches.size(); ++j) {
2475       const Match& match = cases[i].matches[j];
2476       SCOPED_TRACE(" and match index: " + base::IntToString(j));
2477       EXPECT_EQ(match.contents,
2478                 base::UTF16ToUTF8(matches[j].contents));
2479       EXPECT_EQ(match.description,
2480                 base::UTF16ToUTF8(matches[j].description));
2481       EXPECT_EQ(match.query_params,
2482                 matches[j].search_terms_args->suggest_query_params);
2483       EXPECT_EQ(match.fill_into_edit,
2484                 base::UTF16ToUTF8(matches[j].fill_into_edit));
2485       EXPECT_EQ(match.type, matches[j].type);
2486     }
2487     // Ensure that no expected matches are missing.
2488     for (; j < ARRAYSIZE_UNSAFE(cases[i].matches); ++j) {
2489       SCOPED_TRACE(" and match index: " + base::IntToString(j));
2490       EXPECT_EQ(cases[i].matches[j].contents, kNotApplicable);
2491       EXPECT_EQ(cases[i].matches[j].description, kNotApplicable);
2492       EXPECT_EQ(cases[i].matches[j].query_params, kNotApplicable);
2493       EXPECT_EQ(cases[i].matches[j].fill_into_edit, kNotApplicable);
2494       EXPECT_EQ(cases[i].matches[j].type, AutocompleteMatchType::NUM_TYPES);
2495     }
2496   }
2497 }
2498 #endif  // !defined(OS_WIN)
2499
2500
2501 // A basic test that verifies the prefetch metadata parsing logic.
2502 TEST_F(SearchProviderTest, PrefetchMetadataParsing) {
2503   struct Match {
2504     std::string contents;
2505     bool allowed_to_be_prefetched;
2506     AutocompleteMatchType::Type type;
2507     bool from_keyword;
2508   };
2509   const Match kEmptyMatch = { kNotApplicable,
2510                               false,
2511                               AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
2512                               false };
2513
2514   struct {
2515     const std::string input_text;
2516     bool prefer_keyword_provider_results;
2517     const std::string default_provider_response_json;
2518     const std::string keyword_provider_response_json;
2519     const Match matches[5];
2520   } cases[] = {
2521     // Default provider response does not have prefetch details. Ensure that the
2522     // suggestions are not marked as prefetch query.
2523     { "a",
2524       false,
2525       "[\"a\",[\"b\", \"c\"],[],[],{\"google:suggestrelevance\":[1, 2]}]",
2526       std::string(),
2527       { { "a", false, AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, false },
2528         { "c", false, AutocompleteMatchType::SEARCH_SUGGEST, false },
2529         { "b", false, AutocompleteMatchType::SEARCH_SUGGEST, false },
2530         kEmptyMatch,
2531         kEmptyMatch
2532       },
2533     },
2534     // Ensure that default provider suggest response prefetch details are
2535     // parsed and recorded in AutocompleteMatch.
2536     { "ab",
2537       false,
2538       "[\"ab\",[\"abc\", \"http://b.com\", \"http://c.com\"],[],[],"
2539           "{\"google:clientdata\":{\"phi\": 0},"
2540           "\"google:suggesttype\":[\"QUERY\", \"NAVIGATION\", \"NAVIGATION\"],"
2541           "\"google:suggestrelevance\":[999, 12, 1]}]",
2542       std::string(),
2543       { { "ab",    false, AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, false },
2544         { "abc",   true,  AutocompleteMatchType::SEARCH_SUGGEST, false },
2545         { "b.com", false, AutocompleteMatchType::NAVSUGGEST, false },
2546         { "c.com", false, AutocompleteMatchType::NAVSUGGEST, false },
2547         kEmptyMatch
2548       },
2549     },
2550     // Default provider suggest response has prefetch details.
2551     // SEARCH_WHAT_YOU_TYPE suggestion outranks SEARCH_SUGGEST suggestion for
2552     // the same query string. Ensure that the prefetch details from
2553     // SEARCH_SUGGEST match are set onto SEARCH_WHAT_YOU_TYPE match.
2554     { "ab",
2555       false,
2556       "[\"ab\",[\"ab\", \"http://ab.com\"],[],[],"
2557           "{\"google:clientdata\":{\"phi\": 0},"
2558           "\"google:suggesttype\":[\"QUERY\", \"NAVIGATION\"],"
2559           "\"google:suggestrelevance\":[99, 98]}]",
2560       std::string(),
2561       { {"ab", true, AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, false },
2562         {"ab.com", false, AutocompleteMatchType::NAVSUGGEST, false },
2563         kEmptyMatch,
2564         kEmptyMatch,
2565         kEmptyMatch
2566       },
2567     },
2568     // Default provider response has prefetch details. We prefer keyword
2569     // provider results. Ensure that prefetch bit for a suggestion from the
2570     // default search provider does not get copied onto a higher-scoring match
2571     // for the same query string from the keyword provider.
2572     { "k a",
2573       true,
2574       "[\"k a\",[\"a\", \"ab\"],[],[], {\"google:clientdata\":{\"phi\": 0},"
2575           "\"google:suggesttype\":[\"QUERY\", \"QUERY\"],"
2576           "\"google:suggestrelevance\":[9, 12]}]",
2577       "[\"a\",[\"b\", \"c\"],[],[],{\"google:suggestrelevance\":[1, 2]}]",
2578       { { "a", false, AutocompleteMatchType::SEARCH_OTHER_ENGINE, true},
2579         { "k a", false, AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, false },
2580         { "ab", false, AutocompleteMatchType::SEARCH_SUGGEST, false },
2581         { "c", false, AutocompleteMatchType::SEARCH_SUGGEST, true },
2582         { "b", false, AutocompleteMatchType::SEARCH_SUGGEST, true }
2583       },
2584     }
2585   };
2586
2587   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
2588     QueryForInput(ASCIIToUTF16(cases[i].input_text), false,
2589                   cases[i].prefer_keyword_provider_results);
2590
2591     // Set up a default fetcher with provided results.
2592     net::TestURLFetcher* fetcher =
2593         test_factory_.GetFetcherByID(
2594             SearchProvider::kDefaultProviderURLFetcherID);
2595     ASSERT_TRUE(fetcher);
2596     fetcher->set_response_code(200);
2597     fetcher->SetResponseString(cases[i].default_provider_response_json);
2598     fetcher->delegate()->OnURLFetchComplete(fetcher);
2599
2600     if (cases[i].prefer_keyword_provider_results) {
2601       // Set up a keyword fetcher with provided results.
2602       net::TestURLFetcher* keyword_fetcher =
2603           test_factory_.GetFetcherByID(
2604               SearchProvider::kKeywordProviderURLFetcherID);
2605       ASSERT_TRUE(keyword_fetcher);
2606       keyword_fetcher->set_response_code(200);
2607       keyword_fetcher->SetResponseString(
2608           cases[i].keyword_provider_response_json);
2609       keyword_fetcher->delegate()->OnURLFetchComplete(keyword_fetcher);
2610       keyword_fetcher = NULL;
2611     }
2612
2613     RunTillProviderDone();
2614
2615     const std::string description =
2616         "for input with json =" + cases[i].default_provider_response_json;
2617     const ACMatches& matches = provider_->matches();
2618     // The top match must inline and score as highly as calculated verbatim.
2619     ASSERT_FALSE(matches.empty());
2620     EXPECT_GE(matches[0].relevance, 1300);
2621
2622     ASSERT_LE(matches.size(), ARRAYSIZE_UNSAFE(cases[i].matches));
2623     // Ensure that the returned matches equal the expectations.
2624     for (size_t j = 0; j < matches.size(); ++j) {
2625       SCOPED_TRACE(description);
2626       EXPECT_EQ(cases[i].matches[j].contents,
2627                 base::UTF16ToUTF8(matches[j].contents));
2628       EXPECT_EQ(cases[i].matches[j].allowed_to_be_prefetched,
2629                 SearchProvider::ShouldPrefetch(matches[j]));
2630       EXPECT_EQ(cases[i].matches[j].type, matches[j].type);
2631       EXPECT_EQ(cases[i].matches[j].from_keyword,
2632                 matches[j].keyword == ASCIIToUTF16("k"));
2633     }
2634   }
2635 }
2636
2637 TEST_F(SearchProviderTest, XSSIGuardedJSONParsing_InvalidResponse) {
2638   ClearAllResults();
2639
2640   std::string input_str("abc");
2641   QueryForInput(ASCIIToUTF16(input_str), false, false);
2642
2643   // Set up a default fetcher with provided results.
2644   net::TestURLFetcher* fetcher =
2645       test_factory_.GetFetcherByID(
2646           SearchProvider::kDefaultProviderURLFetcherID);
2647   ASSERT_TRUE(fetcher);
2648   fetcher->set_response_code(200);
2649   fetcher->SetResponseString("this is a bad non-json response");
2650   fetcher->delegate()->OnURLFetchComplete(fetcher);
2651
2652   RunTillProviderDone();
2653
2654   const ACMatches& matches = provider_->matches();
2655
2656   // Should have exactly one "search what you typed" match
2657   ASSERT_TRUE(matches.size() == 1);
2658   EXPECT_EQ(input_str, base::UTF16ToUTF8(matches[0].contents));
2659   EXPECT_EQ(AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
2660             matches[0].type);
2661 }
2662
2663 // A basic test that verifies that the XSSI guarded JSON response is parsed
2664 // correctly.
2665 TEST_F(SearchProviderTest, XSSIGuardedJSONParsing_ValidResponses) {
2666   struct Match {
2667     std::string contents;
2668     AutocompleteMatchType::Type type;
2669   };
2670   const Match kEmptyMatch = {
2671       kNotApplicable, AutocompleteMatchType::NUM_TYPES
2672   };
2673
2674   struct {
2675     const std::string input_text;
2676     const std::string default_provider_response_json;
2677     const Match matches[4];
2678   } cases[] = {
2679     // No XSSI guard.
2680     { "a",
2681       "[\"a\",[\"b\", \"c\"],[],[],"
2682       "{\"google:suggesttype\":[\"QUERY\",\"QUERY\"],"
2683       "\"google:suggestrelevance\":[1, 2]}]",
2684       { { "a", AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED },
2685         { "c", AutocompleteMatchType::SEARCH_SUGGEST },
2686         { "b", AutocompleteMatchType::SEARCH_SUGGEST },
2687         kEmptyMatch,
2688       },
2689     },
2690     // Standard XSSI guard - )]}'\n.
2691     { "a",
2692       ")]}'\n[\"a\",[\"b\", \"c\"],[],[],"
2693       "{\"google:suggesttype\":[\"QUERY\",\"QUERY\"],"
2694       "\"google:suggestrelevance\":[1, 2]}]",
2695       { { "a", AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED },
2696         { "c", AutocompleteMatchType::SEARCH_SUGGEST },
2697         { "b", AutocompleteMatchType::SEARCH_SUGGEST },
2698         kEmptyMatch,
2699       },
2700     },
2701     // Modified XSSI guard - contains "[".
2702     { "a",
2703       ")]}'\n[)\"[\"a\",[\"b\", \"c\"],[],[],"
2704       "{\"google:suggesttype\":[\"QUERY\",\"QUERY\"],"
2705       "\"google:suggestrelevance\":[1, 2]}]",
2706       { { "a", AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED },
2707         { "c", AutocompleteMatchType::SEARCH_SUGGEST },
2708         { "b", AutocompleteMatchType::SEARCH_SUGGEST },
2709         kEmptyMatch,
2710       },
2711     },
2712   };
2713
2714   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
2715     ClearAllResults();
2716     QueryForInput(ASCIIToUTF16(cases[i].input_text), false, false);
2717
2718     // Set up a default fetcher with provided results.
2719     net::TestURLFetcher* fetcher =
2720         test_factory_.GetFetcherByID(
2721             SearchProvider::kDefaultProviderURLFetcherID);
2722     ASSERT_TRUE(fetcher);
2723     fetcher->set_response_code(200);
2724     fetcher->SetResponseString(cases[i].default_provider_response_json);
2725     fetcher->delegate()->OnURLFetchComplete(fetcher);
2726
2727     RunTillProviderDone();
2728
2729     const ACMatches& matches = provider_->matches();
2730     // The top match must inline and score as highly as calculated verbatim.
2731     ASSERT_FALSE(matches.empty());
2732     EXPECT_GE(matches[0].relevance, 1300);
2733
2734     SCOPED_TRACE("for case: " + base::IntToString(i));
2735     ASSERT_LE(matches.size(), ARRAYSIZE_UNSAFE(cases[i].matches));
2736     size_t j = 0;
2737     // Ensure that the returned matches equal the expectations.
2738     for (; j < matches.size(); ++j) {
2739       SCOPED_TRACE("and match: " + base::IntToString(j));
2740       EXPECT_EQ(cases[i].matches[j].contents,
2741                 base::UTF16ToUTF8(matches[j].contents));
2742       EXPECT_EQ(cases[i].matches[j].type, matches[j].type);
2743     }
2744     for (; j < ARRAYSIZE_UNSAFE(cases[i].matches); ++j) {
2745       SCOPED_TRACE("and match: " + base::IntToString(j));
2746       EXPECT_EQ(cases[i].matches[j].contents, kNotApplicable);
2747       EXPECT_EQ(cases[i].matches[j].type, AutocompleteMatchType::NUM_TYPES);
2748     }
2749   }
2750 }
2751
2752 // Test that deletion url gets set on an AutocompleteMatch when available for a
2753 // personalized query or a personalized URL.
2754 TEST_F(SearchProviderTest, ParseDeletionUrl) {
2755    struct Match {
2756      std::string contents;
2757      std::string deletion_url;
2758      AutocompleteMatchType::Type type;
2759    };
2760
2761    const Match kEmptyMatch = {
2762        kNotApplicable, "", AutocompleteMatchType::NUM_TYPES
2763    };
2764
2765    const char* url[] = {
2766     "http://defaultturl/complete/deleteitems"
2767        "?delq=ab&client=chrome&deltok=xsrf124",
2768     "http://defaultturl/complete/deleteitems"
2769        "?delq=www.amazon.com&client=chrome&deltok=xsrf123",
2770      };
2771
2772    struct {
2773        const std::string input_text;
2774        const std::string response_json;
2775        const Match matches[5];
2776      } cases[] = {
2777        // A deletion URL on a personalized query should be reflected in the
2778        // resulting AutocompleteMatch.
2779        { "a",
2780          "[\"a\",[\"ab\", \"ac\",\"www.amazon.com\"],[],[],"
2781          "{\"google:suggesttype\":[\"PERSONALIZED_QUERY\",\"QUERY\","
2782           "\"PERSONALIZED_NAVIGATION\"],"
2783          "\"google:suggestrelevance\":[3, 2, 1],"
2784          "\"google:suggestdetail\":[{\"du\":"
2785          "\"/complete/deleteitems?delq=ab&client=chrome"
2786           "&deltok=xsrf124\"}, {}, {\"du\":"
2787          "\"/complete/deleteitems?delq=www.amazon.com&"
2788          "client=chrome&deltok=xsrf123\"}]}]",
2789          { { "a", "", AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED },
2790            { "ab", url[0], AutocompleteMatchType::SEARCH_SUGGEST },
2791            { "ac", "", AutocompleteMatchType::SEARCH_SUGGEST },
2792            { "www.amazon.com", url[1],
2793               AutocompleteMatchType::NAVSUGGEST_PERSONALIZED },
2794            kEmptyMatch,
2795          },
2796        },
2797        // Personalized queries or a personalized URL without deletion URLs
2798        // shouldn't cause errors.
2799        { "a",
2800          "[\"a\",[\"ab\", \"ac\"],[],[],"
2801          "{\"google:suggesttype\":[\"PERSONALIZED_QUERY\",\"QUERY\","
2802          "\"PERSONALIZED_NAVIGATION\"],"
2803          "\"google:suggestrelevance\":[1, 2],"
2804          "\"google:suggestdetail\":[{}, {}]}]",
2805          { { "a", "", AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED },
2806            { "ac", "", AutocompleteMatchType::SEARCH_SUGGEST },
2807            { "ab", "", AutocompleteMatchType::SEARCH_SUGGEST },
2808            { "www.amazon.com", "",
2809               AutocompleteMatchType::NAVSUGGEST_PERSONALIZED },
2810            kEmptyMatch,
2811          },
2812        },
2813        // Personalized queries or a personalized URL without
2814        // google:suggestdetail shouldn't cause errors.
2815        { "a",
2816          "[\"a\",[\"ab\", \"ac\"],[],[],"
2817          "{\"google:suggesttype\":[\"PERSONALIZED_QUERY\",\"QUERY\","
2818          "\"PERSONALIZED_NAVIGATION\"],"
2819          "\"google:suggestrelevance\":[1, 2]}]",
2820          { { "a", "", AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED },
2821            { "ac", "", AutocompleteMatchType::SEARCH_SUGGEST },
2822            { "ab", "", AutocompleteMatchType::SEARCH_SUGGEST },
2823            { "www.amazon.com", "",
2824               AutocompleteMatchType::NAVSUGGEST_PERSONALIZED },
2825            kEmptyMatch,
2826          },
2827        },
2828      };
2829
2830      for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
2831        QueryForInput(ASCIIToUTF16(cases[i].input_text), false, false);
2832
2833        net::TestURLFetcher* fetcher = test_factory_.GetFetcherByID(
2834            SearchProvider::kDefaultProviderURLFetcherID);
2835        ASSERT_TRUE(fetcher);
2836        fetcher->set_response_code(200);
2837        fetcher->SetResponseString(cases[i].response_json);
2838        fetcher->delegate()->OnURLFetchComplete(fetcher);
2839
2840        RunTillProviderDone();
2841
2842        const ACMatches& matches = provider_->matches();
2843        ASSERT_FALSE(matches.empty());
2844
2845        SCOPED_TRACE("for input with json = " + cases[i].response_json);
2846
2847        for (size_t j = 0; j < matches.size(); ++j) {
2848          const Match& match = cases[i].matches[j];
2849          SCOPED_TRACE(" and match index: " + base::IntToString(j));
2850          EXPECT_EQ(match.contents, base::UTF16ToUTF8(matches[j].contents));
2851          EXPECT_EQ(match.deletion_url, matches[j].GetAdditionalInfo(
2852              "deletion_url"));
2853        }
2854      }
2855 }
2856
2857 TEST_F(SearchProviderTest, ReflectsBookmarkBarState) {
2858   profile_.GetPrefs()->SetBoolean(prefs::kShowBookmarkBar, false);
2859   base::string16 term = term1_.substr(0, term1_.length() - 1);
2860   QueryForInput(term, true, false);
2861   ASSERT_FALSE(provider_->matches().empty());
2862   EXPECT_EQ(AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
2863             provider_->matches()[0].type);
2864   ASSERT_TRUE(provider_->matches()[0].search_terms_args != NULL);
2865   EXPECT_FALSE(provider_->matches()[0].search_terms_args->bookmark_bar_pinned);
2866
2867   profile_.GetPrefs()->SetBoolean(prefs::kShowBookmarkBar, true);
2868   term = term1_.substr(0, term1_.length() - 1);
2869   QueryForInput(term, true, false);
2870   ASSERT_FALSE(provider_->matches().empty());
2871   EXPECT_EQ(AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
2872             provider_->matches()[0].type);
2873   ASSERT_TRUE(provider_->matches()[0].search_terms_args != NULL);
2874   EXPECT_TRUE(provider_->matches()[0].search_terms_args->bookmark_bar_pinned);
2875 }
2876
2877 TEST_F(SearchProviderTest, CanSendURL) {
2878   TemplateURLData template_url_data;
2879   template_url_data.short_name = ASCIIToUTF16("t");
2880   template_url_data.SetURL("http://www.google.com/{searchTerms}");
2881   template_url_data.suggestions_url = "http://www.google.com/{searchTerms}";
2882   template_url_data.instant_url = "http://does/not/exist?strk=1";
2883   template_url_data.search_terms_replacement_key = "strk";
2884   template_url_data.id = SEARCH_ENGINE_GOOGLE;
2885   TemplateURL google_template_url(&profile_, template_url_data);
2886
2887   // Create field trial.
2888   base::FieldTrial* field_trial = base::FieldTrialList::CreateFieldTrial(
2889       "AutocompleteDynamicTrial_2", "EnableZeroSuggest");
2890   field_trial->group();
2891
2892   // Not signed in.
2893   EXPECT_FALSE(SearchProvider::CanSendURL(
2894       GURL("http://www.google.com/search"),
2895       GURL("https://www.google.com/complete/search"), &google_template_url,
2896       AutocompleteInput::OTHER, &profile_));
2897   SigninManagerBase* signin = SigninManagerFactory::GetForProfile(&profile_);
2898   signin->SetAuthenticatedUsername("test");
2899
2900   // All conditions should be met.
2901   EXPECT_TRUE(SearchProvider::CanSendURL(
2902       GURL("http://www.google.com/search"),
2903       GURL("https://www.google.com/complete/search"), &google_template_url,
2904       AutocompleteInput::OTHER, &profile_));
2905
2906   // Not in field trial.
2907   ResetFieldTrialList();
2908   EXPECT_FALSE(SearchProvider::CanSendURL(
2909       GURL("http://www.google.com/search"),
2910       GURL("https://www.google.com/complete/search"), &google_template_url,
2911       AutocompleteInput::OTHER, &profile_));
2912   field_trial = base::FieldTrialList::CreateFieldTrial(
2913       "AutocompleteDynamicTrial_2", "EnableZeroSuggest");
2914   field_trial->group();
2915
2916   // Invalid page URL.
2917   EXPECT_FALSE(SearchProvider::CanSendURL(
2918       GURL("badpageurl"),
2919       GURL("https://www.google.com/complete/search"), &google_template_url,
2920       AutocompleteInput::OTHER, &profile_));
2921
2922   // Invalid page classification.
2923   EXPECT_FALSE(SearchProvider::CanSendURL(
2924       GURL("http://www.google.com/search"),
2925       GURL("https://www.google.com/complete/search"), &google_template_url,
2926       AutocompleteInput::INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS,
2927       &profile_));
2928
2929   // Invalid page classification.
2930   EXPECT_FALSE(SearchProvider::CanSendURL(
2931       GURL("http://www.google.com/search"),
2932       GURL("https://www.google.com/complete/search"), &google_template_url,
2933       AutocompleteInput::INSTANT_NTP_WITH_OMNIBOX_AS_STARTING_FOCUS,
2934       &profile_));
2935
2936   // HTTPS page URL on same domain as provider.
2937   EXPECT_TRUE(SearchProvider::CanSendURL(
2938       GURL("https://www.google.com/search"),
2939       GURL("https://www.google.com/complete/search"),
2940       &google_template_url, AutocompleteInput::OTHER, &profile_));
2941
2942   // Non-HTTP[S] page URL on same domain as provider.
2943   EXPECT_FALSE(SearchProvider::CanSendURL(
2944       GURL("ftp://www.google.com/search"),
2945       GURL("https://www.google.com/complete/search"), &google_template_url,
2946       AutocompleteInput::OTHER, &profile_));
2947
2948   // Non-HTTP page URL on different domain.
2949   EXPECT_FALSE(SearchProvider::CanSendURL(
2950       GURL("https://www.notgoogle.com/search"),
2951       GURL("https://www.google.com/complete/search"), &google_template_url,
2952       AutocompleteInput::OTHER, &profile_));
2953
2954   // Non-HTTPS provider.
2955   EXPECT_FALSE(SearchProvider::CanSendURL(
2956       GURL("http://www.google.com/search"),
2957       GURL("http://www.google.com/complete/search"), &google_template_url,
2958       AutocompleteInput::OTHER, &profile_));
2959
2960   // Suggest disabled.
2961   profile_.GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, false);
2962   EXPECT_FALSE(SearchProvider::CanSendURL(
2963       GURL("http://www.google.com/search"),
2964       GURL("https://www.google.com/complete/search"), &google_template_url,
2965       AutocompleteInput::OTHER, &profile_));
2966   profile_.GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true);
2967
2968   // Incognito.
2969   EXPECT_FALSE(SearchProvider::CanSendURL(
2970       GURL("http://www.google.com/search"),
2971       GURL("https://www.google.com/complete/search"), &google_template_url,
2972       AutocompleteInput::OTHER, profile_.GetOffTheRecordProfile()));
2973
2974   // Tab sync not enabled.
2975   profile_.GetPrefs()->SetBoolean(sync_driver::prefs::kSyncKeepEverythingSynced,
2976                                   false);
2977   profile_.GetPrefs()->SetBoolean(sync_driver::prefs::kSyncTabs, false);
2978   EXPECT_FALSE(SearchProvider::CanSendURL(
2979       GURL("http://www.google.com/search"),
2980       GURL("https://www.google.com/complete/search"), &google_template_url,
2981       AutocompleteInput::OTHER, &profile_));
2982   profile_.GetPrefs()->SetBoolean(sync_driver::prefs::kSyncTabs, true);
2983
2984   // Tab sync is encrypted.
2985   ProfileSyncService* service =
2986       ProfileSyncServiceFactory::GetInstance()->GetForProfile(&profile_);
2987   syncer::ModelTypeSet encrypted_types = service->GetEncryptedDataTypes();
2988   encrypted_types.Put(syncer::SESSIONS);
2989   service->OnEncryptedTypesChanged(encrypted_types, false);
2990   EXPECT_FALSE(SearchProvider::CanSendURL(
2991       GURL("http://www.google.com/search"),
2992       GURL("https://www.google.com/complete/search"), &google_template_url,
2993       AutocompleteInput::OTHER, &profile_));
2994   encrypted_types.Remove(syncer::SESSIONS);
2995   service->OnEncryptedTypesChanged(encrypted_types, false);
2996
2997   // Check that there were no side effects from previous tests.
2998   EXPECT_TRUE(SearchProvider::CanSendURL(
2999       GURL("http://www.google.com/search"),
3000       GURL("https://www.google.com/complete/search"), &google_template_url,
3001       AutocompleteInput::OTHER, &profile_));
3002 }
3003
3004 TEST_F(SearchProviderTest, TestDeleteMatch) {
3005   AutocompleteMatch match(provider_, 0, true,
3006                           AutocompleteMatchType::SEARCH_SUGGEST);
3007   match.RecordAdditionalInfo(
3008       SearchProvider::kDeletionUrlKey,
3009       "https://www.google.com/complete/deleteitem?q=foo");
3010
3011   // Test a successful deletion request.
3012   provider_->matches_.push_back(match);
3013   provider_->DeleteMatch(match);
3014   EXPECT_FALSE(provider_->deletion_handlers_.empty());
3015   EXPECT_TRUE(provider_->matches_.empty());
3016   // Set up a default fetcher with provided results.
3017   net::TestURLFetcher* fetcher = test_factory_.GetFetcherByID(
3018       SearchProvider::kDeletionURLFetcherID);
3019   ASSERT_TRUE(fetcher);
3020   fetcher->set_response_code(200);
3021   fetcher->delegate()->OnURLFetchComplete(fetcher);
3022   EXPECT_TRUE(provider_->deletion_handlers_.empty());
3023   EXPECT_TRUE(provider_->is_success());
3024
3025   // Test a failing deletion request.
3026   provider_->matches_.push_back(match);
3027   provider_->DeleteMatch(match);
3028   EXPECT_FALSE(provider_->deletion_handlers_.empty());
3029   // Set up a default fetcher with provided results.
3030   fetcher = test_factory_.GetFetcherByID(
3031       SearchProvider::kDeletionURLFetcherID);
3032   ASSERT_TRUE(fetcher);
3033   fetcher->set_response_code(500);
3034   fetcher->delegate()->OnURLFetchComplete(fetcher);
3035   EXPECT_TRUE(provider_->deletion_handlers_.empty());
3036   EXPECT_FALSE(provider_->is_success());
3037 }
3038
3039 TEST_F(SearchProviderTest, TestDeleteHistoryQueryMatch) {
3040   GURL term_url(
3041       AddSearchToHistory(default_t_url_, ASCIIToUTF16("flash games"), 1));
3042   profile_.BlockUntilHistoryProcessesPendingRequests();
3043
3044   AutocompleteMatch games;
3045   QueryForInput(ASCIIToUTF16("fla"), false, false);
3046   profile_.BlockUntilHistoryProcessesPendingRequests();
3047   ASSERT_NO_FATAL_FAILURE(FinishDefaultSuggestQuery());
3048   ASSERT_TRUE(FindMatchWithContents(ASCIIToUTF16("flash games"), &games));
3049
3050   size_t matches_before = provider_->matches().size();
3051   provider_->DeleteMatch(games);
3052   EXPECT_EQ(matches_before - 1, provider_->matches().size());
3053
3054   // Process history deletions.
3055   profile_.BlockUntilHistoryProcessesPendingRequests();
3056
3057   // Check that the match is gone.
3058   QueryForInput(ASCIIToUTF16("fla"), false, false);
3059   profile_.BlockUntilHistoryProcessesPendingRequests();
3060   ASSERT_NO_FATAL_FAILURE(FinishDefaultSuggestQuery());
3061   EXPECT_FALSE(FindMatchWithContents(ASCIIToUTF16("flash games"), &games));
3062 }
3063
3064 // Verifies that duplicates are preserved in AddMatchToMap().
3065 TEST_F(SearchProviderTest, CheckDuplicateMatchesSaved) {
3066   AddSearchToHistory(default_t_url_, ASCIIToUTF16("a"), 1);
3067   AddSearchToHistory(default_t_url_, ASCIIToUTF16("alpha"), 1);
3068   AddSearchToHistory(default_t_url_, ASCIIToUTF16("avid"), 1);
3069
3070   profile_.BlockUntilHistoryProcessesPendingRequests();
3071   QueryForInput(ASCIIToUTF16("a"), false, false);
3072
3073   // Make sure the default provider's suggest service was queried.
3074   net::TestURLFetcher* fetcher = test_factory_.GetFetcherByID(
3075       SearchProvider::kDefaultProviderURLFetcherID);
3076   ASSERT_TRUE(fetcher);
3077
3078   // Tell the SearchProvider the suggest query is done.
3079   fetcher->set_response_code(200);
3080   fetcher->SetResponseString(
3081       "[\"a\",[\"a\", \"alpha\", \"avid\", \"apricot\"],[],[],"
3082       "{\"google:suggestrelevance\":[1450, 1200, 1150, 1100],"
3083       "\"google:verbatimrelevance\":1350}]");
3084   fetcher->delegate()->OnURLFetchComplete(fetcher);
3085   fetcher = NULL;
3086
3087   // Run till the history results complete.
3088   RunTillProviderDone();
3089
3090   AutocompleteMatch verbatim, match_alpha, match_apricot, match_avid;
3091   EXPECT_TRUE(FindMatchWithContents(ASCIIToUTF16("a"), &verbatim));
3092   EXPECT_TRUE(FindMatchWithContents(ASCIIToUTF16("alpha"), &match_alpha));
3093   EXPECT_TRUE(FindMatchWithContents(ASCIIToUTF16("apricot"), &match_apricot));
3094   EXPECT_TRUE(FindMatchWithContents(ASCIIToUTF16("avid"), &match_avid));
3095
3096   // Verbatim match duplicates are added such that each one has a higher
3097   // relevance than the previous one.
3098   EXPECT_EQ(2U, verbatim.duplicate_matches.size());
3099
3100   // Other match duplicates are added in descending relevance order.
3101   EXPECT_EQ(1U, match_alpha.duplicate_matches.size());
3102   EXPECT_EQ(1U, match_avid.duplicate_matches.size());
3103
3104   EXPECT_EQ(0U, match_apricot.duplicate_matches.size());
3105 }