• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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 "components/omnibox/base_search_provider.h"
6 
7 #include "base/strings/string16.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "components/omnibox/autocomplete_match.h"
10 #include "components/omnibox/autocomplete_match_type.h"
11 #include "components/omnibox/autocomplete_provider_client.h"
12 #include "components/omnibox/autocomplete_scheme_classifier.h"
13 #include "components/omnibox/search_suggestion_parser.h"
14 #include "components/search_engines/search_terms_data.h"
15 #include "components/search_engines/template_url_service.h"
16 #include "components/search_engines/template_url_service_client.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 
20 using testing::NiceMock;
21 using testing::Return;
22 using testing::_;
23 
24 class MockAutocompleteProviderClient : public AutocompleteProviderClient {
25  public:
MockAutocompleteProviderClient()26   MockAutocompleteProviderClient() {}
27   MOCK_METHOD0(RequestContext, net::URLRequestContextGetter*());
28   MOCK_METHOD0(IsOffTheRecord, bool());
29   MOCK_METHOD0(AcceptLanguages, std::string());
30   MOCK_METHOD0(SearchSuggestEnabled, bool());
31   MOCK_METHOD0(ShowBookmarkBar, bool());
32   MOCK_METHOD0(SchemeClassifier, const AutocompleteSchemeClassifier&());
33   MOCK_METHOD6(
34       Classify,
35       void(const base::string16& text,
36            bool prefer_keyword,
37            bool allow_exact_keyword_match,
38            metrics::OmniboxEventProto::PageClassification page_classification,
39            AutocompleteMatch* match,
40            GURL* alternate_nav_url));
41   MOCK_METHOD0(InMemoryDatabase, history::URLDatabase*());
42   MOCK_METHOD2(DeleteMatchingURLsForKeywordFromHistory,
43                void(history::KeywordID keyword_id, const base::string16& term));
44   MOCK_METHOD0(TabSyncEnabledAndUnencrypted, bool());
45   MOCK_METHOD1(PrefetchImage, void(const GURL& url));
46 
47  private:
48   DISALLOW_COPY_AND_ASSIGN(MockAutocompleteProviderClient);
49 };
50 
51 class TestBaseSearchProvider : public BaseSearchProvider {
52  public:
53   typedef BaseSearchProvider::MatchMap MatchMap;
54 
55   // Note: Takes ownership of client. scoped_ptr<> would be the right way to
56   // express that, but NiceMock<> can't forward a scoped_ptr.
TestBaseSearchProvider(TemplateURLService * template_url_service,AutocompleteProviderClient * client,AutocompleteProvider::Type type)57   TestBaseSearchProvider(TemplateURLService* template_url_service,
58                          AutocompleteProviderClient* client,
59                          AutocompleteProvider::Type type)
60       : BaseSearchProvider(template_url_service,
61                            scoped_ptr<AutocompleteProviderClient>(client),
62                            type) {}
63   MOCK_METHOD1(DeleteMatch, void(const AutocompleteMatch& match));
64   MOCK_CONST_METHOD1(AddProviderInfo, void(ProvidersInfo* provider_info));
65   MOCK_CONST_METHOD1(GetTemplateURL, const TemplateURL*(bool is_keyword));
66   MOCK_CONST_METHOD1(GetInput, const AutocompleteInput(bool is_keyword));
67   MOCK_CONST_METHOD1(ShouldAppendExtraParams,
68                      bool(const SearchSuggestionParser::SuggestResult& result));
69   MOCK_METHOD1(RecordDeletionResult, void(bool success));
70 
71   MOCK_METHOD2(Start,
72                void(const AutocompleteInput& input, bool minimal_changes));
AddMatchToMap(const SearchSuggestionParser::SuggestResult & result,const std::string & metadata,int accepted_suggestion,bool mark_as_deletable,bool in_keyword_mode,MatchMap * map)73   void AddMatchToMap(const SearchSuggestionParser::SuggestResult& result,
74                      const std::string& metadata,
75                      int accepted_suggestion,
76                      bool mark_as_deletable,
77                      bool in_keyword_mode,
78                      MatchMap* map) {
79     BaseSearchProvider::AddMatchToMap(result,
80                                       metadata,
81                                       accepted_suggestion,
82                                       mark_as_deletable,
83                                       in_keyword_mode,
84                                       map);
85   }
86 
87  protected:
~TestBaseSearchProvider()88   virtual ~TestBaseSearchProvider() {}
89 
90  private:
91   DISALLOW_COPY_AND_ASSIGN(TestBaseSearchProvider);
92 };
93 
94 class BaseSearchProviderTest : public testing::Test {
95  public:
~BaseSearchProviderTest()96   virtual ~BaseSearchProviderTest() {}
97 
98  protected:
SetUp()99   virtual void SetUp() {
100     service_.reset(
101         new TemplateURLService(NULL,
102                                scoped_ptr<SearchTermsData>(new SearchTermsData),
103                                NULL,
104                                scoped_ptr<TemplateURLServiceClient>(),
105                                NULL,
106                                NULL,
107                                base::Closure()));
108     provider_ = new NiceMock<TestBaseSearchProvider>(
109         service_.get(),
110         new NiceMock<MockAutocompleteProviderClient>,
111         AutocompleteProvider::TYPE_SEARCH);
112   }
113 
114   scoped_refptr<NiceMock<TestBaseSearchProvider> > provider_;
115   scoped_ptr<TemplateURLService> service_;
116 };
117 
TEST_F(BaseSearchProviderTest,PreserveAnswersWhenDeduplicating)118 TEST_F(BaseSearchProviderTest, PreserveAnswersWhenDeduplicating) {
119   TemplateURLData data;
120   data.SetURL("http://foo.com/url?bar={searchTerms}");
121   scoped_ptr<TemplateURL> template_url(new TemplateURL(data));
122 
123   TestBaseSearchProvider::MatchMap map;
124   base::string16 query = base::ASCIIToUTF16("weather los angeles");
125   base::string16 answer_contents = base::ASCIIToUTF16("some answer content");
126   base::string16 answer_type = base::ASCIIToUTF16("2334");
127 
128   EXPECT_CALL(*provider_, GetInput(_))
129       .WillRepeatedly(Return(AutocompleteInput()));
130   EXPECT_CALL(*provider_, GetTemplateURL(_))
131       .WillRepeatedly(Return(template_url.get()));
132 
133   SearchSuggestionParser::SuggestResult more_relevant(
134       query, AutocompleteMatchType::SEARCH_HISTORY, query, base::string16(),
135       base::string16(), base::string16(), base::string16(), std::string(),
136       std::string(), false, 1300, true, false, query);
137   provider_->AddMatchToMap(
138       more_relevant, std::string(), TemplateURLRef::NO_SUGGESTION_CHOSEN,
139       false, false, &map);
140 
141   SearchSuggestionParser::SuggestResult less_relevant(
142       query, AutocompleteMatchType::SEARCH_SUGGEST, query, base::string16(),
143       base::string16(), answer_contents, answer_type, std::string(),
144       std::string(), false, 850, true, false, query);
145   provider_->AddMatchToMap(
146       less_relevant, std::string(), TemplateURLRef::NO_SUGGESTION_CHOSEN,
147       false, false, &map);
148 
149   ASSERT_EQ(1U, map.size());
150   AutocompleteMatch match = map.begin()->second;
151   ASSERT_EQ(1U, match.duplicate_matches.size());
152   AutocompleteMatch duplicate = match.duplicate_matches[0];
153 
154   EXPECT_EQ(answer_contents, match.answer_contents);
155   EXPECT_EQ(answer_type, match.answer_type);
156   EXPECT_EQ(AutocompleteMatchType::SEARCH_HISTORY, match.type);
157   EXPECT_EQ(1300, match.relevance);
158 
159   EXPECT_EQ(answer_contents, duplicate.answer_contents);
160   EXPECT_EQ(answer_type, duplicate.answer_type);
161   EXPECT_EQ(AutocompleteMatchType::SEARCH_SUGGEST, duplicate.type);
162   EXPECT_EQ(850, duplicate.relevance);
163 
164   // Ensure answers are not copied over existing answers.
165   map.clear();
166   base::string16 answer_contents2 = base::ASCIIToUTF16("different answer");
167   more_relevant = SearchSuggestionParser::SuggestResult(
168       query, AutocompleteMatchType::SEARCH_HISTORY, query, base::string16(),
169       base::string16(), answer_contents2, answer_type, std::string(),
170       std::string(), false, 1300, true, false, query);
171   provider_->AddMatchToMap(
172       more_relevant, std::string(), TemplateURLRef::NO_SUGGESTION_CHOSEN,
173       false, false, &map);
174   provider_->AddMatchToMap(
175       less_relevant, std::string(), TemplateURLRef::NO_SUGGESTION_CHOSEN,
176       false, false, &map);
177   ASSERT_EQ(1U, map.size());
178   match = map.begin()->second;
179   ASSERT_EQ(1U, match.duplicate_matches.size());
180   duplicate = match.duplicate_matches[0];
181 
182   EXPECT_EQ(answer_contents2, match.answer_contents);
183   EXPECT_EQ(answer_type, match.answer_type);
184   EXPECT_EQ(AutocompleteMatchType::SEARCH_HISTORY, match.type);
185   EXPECT_EQ(1300, match.relevance);
186 
187   EXPECT_EQ(answer_contents, duplicate.answer_contents);
188   EXPECT_EQ(answer_type, duplicate.answer_type);
189   EXPECT_EQ(AutocompleteMatchType::SEARCH_SUGGEST, duplicate.type);
190   EXPECT_EQ(850, duplicate.relevance);
191 
192 }
193