OLD | NEW |
---|---|
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/autocomplete/search_provider.h" | 5 #include "chrome/browser/autocomplete/search_provider.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 | 9 |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
11 #include "base/i18n/break_iterator.h" | 11 #include "base/i18n/break_iterator.h" |
12 #include "base/i18n/case_conversion.h" | 12 #include "base/i18n/case_conversion.h" |
13 #include "base/i18n/icu_string_conversions.h" | 13 #include "base/i18n/icu_string_conversions.h" |
14 #include "base/json/json_string_value_serializer.h" | 14 #include "base/json/json_string_value_serializer.h" |
15 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
16 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
17 #include "base/prefs/pref_service.h" | 17 #include "base/prefs/pref_service.h" |
18 #include "base/strings/string16.h" | 18 #include "base/strings/string16.h" |
19 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
20 #include "base/strings/utf_string_conversions.h" | 20 #include "base/strings/utf_string_conversions.h" |
21 #include "chrome/browser/autocomplete/autocomplete_classifier.h" | 21 #include "chrome/browser/autocomplete/autocomplete_classifier.h" |
22 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" | 22 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" |
23 #include "chrome/browser/autocomplete/autocomplete_match.h" | 23 #include "chrome/browser/autocomplete/autocomplete_match.h" |
24 #include "chrome/browser/autocomplete/autocomplete_provider_listener.h" | 24 #include "chrome/browser/autocomplete/autocomplete_provider_listener.h" |
25 #include "chrome/browser/autocomplete/autocomplete_result.h" | 25 #include "chrome/browser/autocomplete/autocomplete_result.h" |
26 #include "chrome/browser/autocomplete/base_search_provider.h" | |
26 #include "chrome/browser/autocomplete/keyword_provider.h" | 27 #include "chrome/browser/autocomplete/keyword_provider.h" |
27 #include "chrome/browser/autocomplete/url_prefix.h" | 28 #include "chrome/browser/autocomplete/url_prefix.h" |
28 #include "chrome/browser/google/google_util.h" | 29 #include "chrome/browser/google/google_util.h" |
29 #include "chrome/browser/history/history_service.h" | 30 #include "chrome/browser/history/history_service.h" |
30 #include "chrome/browser/history/history_service_factory.h" | 31 #include "chrome/browser/history/history_service_factory.h" |
31 #include "chrome/browser/history/in_memory_database.h" | 32 #include "chrome/browser/history/in_memory_database.h" |
32 #include "chrome/browser/metrics/variations/variations_http_header_provider.h" | 33 #include "chrome/browser/metrics/variations/variations_http_header_provider.h" |
33 #include "chrome/browser/omnibox/omnibox_field_trial.h" | 34 #include "chrome/browser/omnibox/omnibox_field_trial.h" |
34 #include "chrome/browser/profiles/profile.h" | 35 #include "chrome/browser/profiles/profile.h" |
35 #include "chrome/browser/search/search.h" | 36 #include "chrome/browser/search/search.h" |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
168 DCHECK(source == deletion_fetcher_.get()); | 169 DCHECK(source == deletion_fetcher_.get()); |
169 callback_.Run( | 170 callback_.Run( |
170 source->GetStatus().is_success() && (source->GetResponseCode() == 200), | 171 source->GetStatus().is_success() && (source->GetResponseCode() == 200), |
171 this); | 172 this); |
172 }; | 173 }; |
173 | 174 |
174 | 175 |
175 // SearchProvider::Providers -------------------------------------------------- | 176 // SearchProvider::Providers -------------------------------------------------- |
176 | 177 |
177 SearchProvider::Providers::Providers(TemplateURLService* template_url_service) | 178 SearchProvider::Providers::Providers(TemplateURLService* template_url_service) |
178 : template_url_service_(template_url_service) { | 179 : template_url_service_(template_url_service) {} |
179 } | |
180 | 180 |
181 const TemplateURL* SearchProvider::Providers::GetDefaultProviderURL() const { | 181 const TemplateURL* SearchProvider::Providers::GetDefaultProviderURL() const { |
182 return default_provider_.empty() ? NULL : | 182 return default_provider_.empty() ? NULL : |
183 template_url_service_->GetTemplateURLForKeyword(default_provider_); | 183 template_url_service_->GetTemplateURLForKeyword(default_provider_); |
184 } | 184 } |
185 | 185 |
186 const TemplateURL* SearchProvider::Providers::GetKeywordProviderURL() const { | 186 const TemplateURL* SearchProvider::Providers::GetKeywordProviderURL() |
H Fung
2014/01/30 02:35:33
I'm not sure why you changed this since it had fit
Maria
2014/01/30 02:47:02
Done.
| |
187 const { | |
187 return keyword_provider_.empty() ? NULL : | 188 return keyword_provider_.empty() ? NULL : |
188 template_url_service_->GetTemplateURLForKeyword(keyword_provider_); | 189 template_url_service_->GetTemplateURLForKeyword(keyword_provider_); |
189 } | 190 } |
190 | 191 |
191 | 192 |
192 // SearchProvider::Result ----------------------------------------------------- | |
193 | |
194 SearchProvider::Result::Result(bool from_keyword_provider, | |
195 int relevance, | |
196 bool relevance_from_server) | |
197 : from_keyword_provider_(from_keyword_provider), | |
198 relevance_(relevance), | |
199 relevance_from_server_(relevance_from_server) { | |
200 } | |
201 | |
202 SearchProvider::Result::~Result() { | |
203 } | |
204 | |
205 | |
206 // SearchProvider::SuggestResult ---------------------------------------------- | |
207 | |
208 SearchProvider::SuggestResult::SuggestResult( | |
209 const base::string16& suggestion, | |
210 AutocompleteMatchType::Type type, | |
211 const base::string16& match_contents, | |
212 const base::string16& annotation, | |
213 const std::string& suggest_query_params, | |
214 const std::string& deletion_url, | |
215 bool from_keyword_provider, | |
216 int relevance, | |
217 bool relevance_from_server, | |
218 bool should_prefetch, | |
219 const base::string16& input_text) | |
220 : Result(from_keyword_provider, relevance, relevance_from_server), | |
221 suggestion_(suggestion), | |
222 type_(type), | |
223 annotation_(annotation), | |
224 suggest_query_params_(suggest_query_params), | |
225 deletion_url_(deletion_url), | |
226 should_prefetch_(should_prefetch) { | |
227 match_contents_ = match_contents; | |
228 DCHECK(!match_contents_.empty()); | |
229 ClassifyMatchContents(true, input_text); | |
230 } | |
231 | |
232 SearchProvider::SuggestResult::~SuggestResult() { | |
233 } | |
234 | |
235 void SearchProvider::SuggestResult::ClassifyMatchContents( | |
236 const bool allow_bolding_all, | |
237 const base::string16& input_text) { | |
238 size_t input_position = match_contents_.find(input_text); | |
239 if (!allow_bolding_all && (input_position == base::string16::npos)) { | |
240 // Bail if the code below to update the bolding would bold the whole | |
241 // string. Note that the string may already be entirely bolded; if | |
242 // so, leave it as is. | |
243 return; | |
244 } | |
245 match_contents_class_.clear(); | |
246 // We do intra-string highlighting for suggestions - the suggested segment | |
247 // will be highlighted, e.g. for input_text = "you" the suggestion may be | |
248 // "youtube", so we'll bold the "tube" section: you*tube*. | |
249 if (input_text != match_contents_) { | |
250 if (input_position == base::string16::npos) { | |
251 // The input text is not a substring of the query string, e.g. input | |
252 // text is "slasdot" and the query string is "slashdot", so we bold the | |
253 // whole thing. | |
254 match_contents_class_.push_back(ACMatchClassification( | |
255 0, ACMatchClassification::MATCH)); | |
256 } else { | |
257 // We don't iterate over the string here annotating all matches because | |
258 // it looks odd to have every occurrence of a substring that may be as | |
259 // short as a single character highlighted in a query suggestion result, | |
260 // e.g. for input text "s" and query string "southwest airlines", it | |
261 // looks odd if both the first and last s are highlighted. | |
262 if (input_position != 0) { | |
263 match_contents_class_.push_back(ACMatchClassification( | |
264 0, ACMatchClassification::MATCH)); | |
265 } | |
266 match_contents_class_.push_back( | |
267 ACMatchClassification(input_position, ACMatchClassification::NONE)); | |
268 size_t next_fragment_position = input_position + input_text.length(); | |
269 if (next_fragment_position < match_contents_.length()) { | |
270 match_contents_class_.push_back(ACMatchClassification( | |
271 next_fragment_position, ACMatchClassification::MATCH)); | |
272 } | |
273 } | |
274 } else { | |
275 // Otherwise, match_contents_ is a verbatim (what-you-typed) match, either | |
276 // for the default provider or a keyword search provider. | |
277 match_contents_class_.push_back(ACMatchClassification( | |
278 0, ACMatchClassification::NONE)); | |
279 } | |
280 } | |
281 | |
282 bool SearchProvider::SuggestResult::IsInlineable( | |
283 const base::string16& input) const { | |
284 return StartsWith(suggestion_, input, false); | |
285 } | |
286 | |
287 int SearchProvider::SuggestResult::CalculateRelevance( | |
288 const AutocompleteInput& input, | |
289 bool keyword_provider_requested) const { | |
290 if (!from_keyword_provider_ && keyword_provider_requested) | |
291 return 100; | |
292 return ((input.type() == AutocompleteInput::URL) ? 300 : 600); | |
293 } | |
294 | |
295 | |
296 // SearchProvider::NavigationResult ------------------------------------------- | |
297 | |
298 SearchProvider::NavigationResult::NavigationResult( | |
299 const AutocompleteProvider& provider, | |
300 const GURL& url, | |
301 const base::string16& description, | |
302 bool from_keyword_provider, | |
303 int relevance, | |
304 bool relevance_from_server, | |
305 const base::string16& input_text, | |
306 const std::string& languages) | |
307 : Result(from_keyword_provider, relevance, relevance_from_server), | |
308 url_(url), | |
309 formatted_url_(AutocompleteInput::FormattedStringWithEquivalentMeaning( | |
310 url, provider.StringForURLDisplay(url, true, false))), | |
311 description_(description) { | |
312 DCHECK(url_.is_valid()); | |
313 CalculateAndClassifyMatchContents(true, input_text, languages); | |
314 } | |
315 | |
316 SearchProvider::NavigationResult::~NavigationResult() { | |
317 } | |
318 | |
319 void SearchProvider::NavigationResult::CalculateAndClassifyMatchContents( | |
320 const bool allow_bolding_nothing, | |
321 const base::string16& input_text, | |
322 const std::string& languages) { | |
323 // First look for the user's input inside the formatted url as it would be | |
324 // without trimming the scheme, so we can find matches at the beginning of the | |
325 // scheme. | |
326 const URLPrefix* prefix = | |
327 URLPrefix::BestURLPrefix(formatted_url_, input_text); | |
328 size_t match_start = (prefix == NULL) ? | |
329 formatted_url_.find(input_text) : prefix->prefix.length(); | |
330 bool trim_http = !AutocompleteInput::HasHTTPScheme(input_text) && | |
331 (!prefix || (match_start != 0)); | |
332 const net::FormatUrlTypes format_types = | |
333 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP); | |
334 | |
335 base::string16 match_contents = net::FormatUrl(url_, languages, format_types, | |
336 net::UnescapeRule::SPACES, NULL, NULL, &match_start); | |
337 // If the first match in the untrimmed string was inside a scheme that we | |
338 // trimmed, look for a subsequent match. | |
339 if (match_start == base::string16::npos) | |
340 match_start = match_contents.find(input_text); | |
341 // Update |match_contents_| and |match_contents_class_| if it's allowed. | |
342 if (allow_bolding_nothing || (match_start != base::string16::npos)) { | |
343 match_contents_ = match_contents; | |
344 // Safe if |match_start| is npos; also safe if the input is longer than the | |
345 // remaining contents after |match_start|. | |
346 AutocompleteMatch::ClassifyLocationInString(match_start, | |
347 input_text.length(), match_contents_.length(), | |
348 ACMatchClassification::URL, &match_contents_class_); | |
349 } | |
350 } | |
351 | |
352 bool SearchProvider::NavigationResult::IsInlineable( | |
353 const base::string16& input) const { | |
354 return URLPrefix::BestURLPrefix(formatted_url_, input) != NULL; | |
355 } | |
356 | |
357 int SearchProvider::NavigationResult::CalculateRelevance( | |
358 const AutocompleteInput& input, | |
359 bool keyword_provider_requested) const { | |
360 return (from_keyword_provider_ || !keyword_provider_requested) ? 800 : 150; | |
361 } | |
362 | |
363 | |
364 // SearchProvider::CompareScoredResults --------------------------------------- | 193 // SearchProvider::CompareScoredResults --------------------------------------- |
365 | 194 |
366 class SearchProvider::CompareScoredResults { | 195 class SearchProvider::CompareScoredResults { |
367 public: | 196 public: |
368 bool operator()(const Result& a, const Result& b) { | 197 bool operator()(const Result& a, const Result& b) { |
369 // Sort in descending relevance order. | 198 // Sort in descending relevance order. |
370 return a.relevance() > b.relevance(); | 199 return a.relevance() > b.relevance(); |
371 } | 200 } |
372 }; | 201 }; |
373 | 202 |
374 | 203 |
375 // SearchProvider::Results ---------------------------------------------------- | |
376 | |
377 SearchProvider::Results::Results() : verbatim_relevance(-1) { | |
378 } | |
379 | |
380 SearchProvider::Results::~Results() { | |
381 } | |
382 | |
383 void SearchProvider::Results::Clear() { | |
384 suggest_results.clear(); | |
385 navigation_results.clear(); | |
386 verbatim_relevance = -1; | |
387 metadata.clear(); | |
388 } | |
389 | |
390 bool SearchProvider::Results::HasServerProvidedScores() const { | |
391 if (verbatim_relevance >= 0) | |
392 return true; | |
393 | |
394 // Right now either all results of one type will be server-scored or they will | |
395 // all be locally scored, but in case we change this later, we'll just check | |
396 // them all. | |
397 for (SuggestResults::const_iterator i(suggest_results.begin()); | |
398 i != suggest_results.end(); ++i) { | |
399 if (i->relevance_from_server()) | |
400 return true; | |
401 } | |
402 for (NavigationResults::const_iterator i(navigation_results.begin()); | |
403 i != navigation_results.end(); ++i) { | |
404 if (i->relevance_from_server()) | |
405 return true; | |
406 } | |
407 | |
408 return false; | |
409 } | |
410 | |
411 | |
412 // SearchProvider ------------------------------------------------------------- | 204 // SearchProvider ------------------------------------------------------------- |
413 | 205 |
414 // static | 206 // static |
415 const int SearchProvider::kDefaultProviderURLFetcherID = 1; | 207 const int SearchProvider::kDefaultProviderURLFetcherID = 1; |
416 const int SearchProvider::kKeywordProviderURLFetcherID = 2; | 208 const int SearchProvider::kKeywordProviderURLFetcherID = 2; |
417 const int SearchProvider::kDeletionURLFetcherID = 3; | 209 const int SearchProvider::kDeletionURLFetcherID = 3; |
418 int SearchProvider::kMinimumTimeBetweenSuggestQueriesMs = 100; | 210 int SearchProvider::kMinimumTimeBetweenSuggestQueriesMs = 100; |
419 const char SearchProvider::kRelevanceFromServerKey[] = "relevance_from_server"; | 211 const char SearchProvider::kRelevanceFromServerKey[] = "relevance_from_server"; |
420 const char SearchProvider::kShouldPrefetchKey[] = "should_prefetch"; | 212 const char SearchProvider::kShouldPrefetchKey[] = "should_prefetch"; |
421 const char SearchProvider::kSuggestMetadataKey[] = "suggest_metadata"; | 213 const char SearchProvider::kSuggestMetadataKey[] = "suggest_metadata"; |
422 const char SearchProvider::kDeletionUrlKey[] = "deletion_url"; | 214 const char SearchProvider::kDeletionUrlKey[] = "deletion_url"; |
423 const char SearchProvider::kTrue[] = "true"; | 215 const char SearchProvider::kTrue[] = "true"; |
424 const char SearchProvider::kFalse[] = "false"; | 216 const char SearchProvider::kFalse[] = "false"; |
425 | 217 |
426 SearchProvider::SearchProvider(AutocompleteProviderListener* listener, | 218 SearchProvider::SearchProvider(AutocompleteProviderListener* listener, |
427 Profile* profile) | 219 Profile* profile) |
428 : AutocompleteProvider(listener, profile, | 220 : BaseSearchProvider(listener, profile, AutocompleteProvider::TYPE_SEARCH), |
429 AutocompleteProvider::TYPE_SEARCH), | |
430 providers_(TemplateURLServiceFactory::GetForProfile(profile)), | 221 providers_(TemplateURLServiceFactory::GetForProfile(profile)), |
431 suggest_results_pending_(0), | 222 suggest_results_pending_(0), |
432 field_trial_triggered_(false), | 223 field_trial_triggered_(false), |
433 field_trial_triggered_in_session_(false) { | 224 field_trial_triggered_in_session_(false) { |
434 } | 225 } |
435 | 226 |
436 // static | 227 // static |
437 AutocompleteMatch SearchProvider::CreateSearchSuggestion( | 228 AutocompleteMatch SearchProvider::CreateSearchSuggestion( |
438 AutocompleteProvider* autocomplete_provider, | 229 AutocompleteProvider* autocomplete_provider, |
439 const AutocompleteInput& input, | 230 const AutocompleteInput& input, |
(...skipping 1648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2088 if (!OmniboxFieldTrial::InZeroSuggestFieldTrial() || | 1879 if (!OmniboxFieldTrial::InZeroSuggestFieldTrial() || |
2089 service == NULL || | 1880 service == NULL || |
2090 !service->IsSyncEnabledAndLoggedIn() || | 1881 !service->IsSyncEnabledAndLoggedIn() || |
2091 !sync_prefs.GetPreferredDataTypes(syncer::UserTypes()).Has( | 1882 !sync_prefs.GetPreferredDataTypes(syncer::UserTypes()).Has( |
2092 syncer::PROXY_TABS) || | 1883 syncer::PROXY_TABS) || |
2093 service->GetEncryptedDataTypes().Has(syncer::SESSIONS)) | 1884 service->GetEncryptedDataTypes().Has(syncer::SESSIONS)) |
2094 return false; | 1885 return false; |
2095 | 1886 |
2096 return true; | 1887 return true; |
2097 } | 1888 } |
OLD | NEW |