12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/omnibox/search_provider.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cmath> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/base64.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/break_iterator.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/case_conversion.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_string_value_serializer.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/metrics/user_metrics.h" 17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/rand_util.h" 1823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/strings/string_util.h" 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/history/core/browser/in_memory_database.h" 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/history/core/browser/keyword_search_term.h" 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/metrics/proto/omnibox_input_type.pb.h" 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/omnibox/autocomplete_provider_client.h" 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/omnibox/autocomplete_provider_listener.h" 256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/omnibox/autocomplete_result.h" 2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/omnibox/keyword_provider.h" 276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/omnibox/omnibox_field_trial.h" 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/omnibox/url_prefix.h" 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/search/search.h" 30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/search_engines/template_url_prepopulate_data.h" 31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/search_engines/template_url_service.h" 32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/variations/variations_http_header_provider.h" 3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "grit/components_strings.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/escape.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/load_flags.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/http_request_headers.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_status.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "url/url_constants.h" 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/url_util.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Helpers -------------------------------------------------------------------- 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We keep track in a histogram how many suggest requests we send, how 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// many suggest requests we invalidate (e.g., due to a user typing 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// another character), and how many replies we receive. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// *** ADD NEW ENUMS AFTER ALL PREVIOUSLY DEFINED ONES! *** 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (excluding the end-of-list enum value) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We do not want values of existing enums to change or else it screws 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// up the statistics. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum SuggestRequestsHistogramValue { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) REQUEST_SENT = 1, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) REQUEST_INVALIDATED, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) REPLY_RECEIVED, 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MAX_SUGGEST_REQUEST_HISTOGRAM_VALUE 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The verbatim score for an input which is not an URL. 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kNonURLVerbatimRelevance = 1300; 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Increments the appropriate value in the histogram by one. 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LogOmniboxSuggestRequest( 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SuggestRequestsHistogramValue request_value) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Omnibox.SuggestRequests", request_value, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MAX_SUGGEST_REQUEST_HISTOGRAM_VALUE); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool HasMultipleWords(const base::string16& text) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::i18n::BreakIterator i(text, base::i18n::BreakIterator::BREAK_WORD); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool found_word = false; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i.Init()) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (i.Advance()) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i.IsWord()) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found_word) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_word = true; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SearchProvider::Providers -------------------------------------------------- 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SearchProvider::Providers::Providers(TemplateURLService* template_url_service) 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : template_url_service_(template_url_service) {} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const TemplateURL* SearchProvider::Providers::GetDefaultProviderURL() const { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return default_provider_.empty() ? NULL : 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->GetTemplateURLForKeyword(default_provider_); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const TemplateURL* SearchProvider::Providers::GetKeywordProviderURL() const { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return keyword_provider_.empty() ? NULL : 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template_url_service_->GetTemplateURLForKeyword(keyword_provider_); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// SearchProvider::CompareScoredResults --------------------------------------- 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass SearchProvider::CompareScoredResults { 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public: 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool operator()(const SearchSuggestionParser::Result& a, 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const SearchSuggestionParser::Result& b) { 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Sort in descending relevance order. 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return a.relevance() > b.relevance(); 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SearchProvider ------------------------------------------------------------- 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int SearchProvider::kMinimumTimeBetweenSuggestQueriesMs = 100; 121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciSearchProvider::SearchProvider( 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AutocompleteProviderListener* listener, 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TemplateURLService* template_url_service, 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<AutocompleteProviderClient> client) 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : BaseSearchProvider(template_url_service, client.Pass(), 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) AutocompleteProvider::TYPE_SEARCH), 1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) listener_(listener), 1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) suggest_results_pending_(0), 13003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) providers_(template_url_service), 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci answers_cache_(10) { 132424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 133424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 134424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// static 135424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)std::string SearchProvider::GetSuggestMetadata(const AutocompleteMatch& match) { 136424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return match.GetAdditionalInfo(kSuggestMetadataKey); 137424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 138424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SearchProvider::ResetSession() { 140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch field_trial_triggered_in_session_ = false; 141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSearchProvider::~SearchProvider() { 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// static 147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint SearchProvider::CalculateRelevanceForKeywordVerbatim( 1486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) metrics::OmniboxInputType::Type type, 149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool prefer_keyword) { 150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // This function is responsible for scoring verbatim query matches 151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // for non-extension keywords. KeywordProvider::CalculateRelevance() 152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // scores verbatim query matches for extension keywords, as well as 153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // for keyword matches (i.e., suggestions of a keyword itself, not a 154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // suggestion of a query on a keyword search engine). These two 155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // functions are currently in sync, but there's no reason we 156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // couldn't decide in the future to score verbatim matches 157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // differently for extension and non-extension keywords. If you 158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // make such a change, however, you should update this comment to 159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // describe it, so it's clear why the functions diverge. 160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (prefer_keyword) 161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return 1500; 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return (type == metrics::OmniboxInputType::QUERY) ? 1450 : 1100; 1635e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} 1645e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SearchProvider::UpdateOldResults( 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool minimal_changes, 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SearchSuggestionParser::Results* results) { 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // When called without |minimal_changes|, it likely means the user has 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // pressed a key. Revise the cached results appropriately. 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!minimal_changes) { 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (SearchSuggestionParser::SuggestResults::iterator sug_it = 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci results->suggest_results.begin(); 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sug_it != results->suggest_results.end(); ++sug_it) { 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sug_it->set_received_after_last_keystroke(false); 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (SearchSuggestionParser::NavigationResults::iterator nav_it = 1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci results->navigation_results.begin(); 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci nav_it != results->navigation_results.end(); ++nav_it) { 1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci nav_it->set_received_after_last_keystroke(false); 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciACMatches::iterator SearchProvider::FindTopMatch(ACMatches* matches) { 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ACMatches::iterator it = matches->begin(); 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci while ((it != matches->end()) && !it->allowed_to_be_default_match) 1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++it; 1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return it; 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SearchProvider::Start(const AutocompleteInput& input, 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool minimal_changes) { 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Do our best to load the model as early as possible. This will reduce 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // odds of having the model not ready when really needed (a non-empty input). 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TemplateURLService* model = providers_.template_url_service(); 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(model); 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) model->Load(); 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) matches_.clear(); 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) field_trial_triggered_ = false; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Can't return search/suggest results for bogus input. 2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (input.type() == metrics::OmniboxInputType::INVALID) { 206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Stop(true); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) keyword_input_ = input; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TemplateURL* keyword_provider = 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) KeywordProvider::GetSubstitutingTemplateURLForInput(model, 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &keyword_input_); 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (keyword_provider == NULL) 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) keyword_input_.Clear(); 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else if (keyword_input_.text().empty()) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_provider = NULL; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TemplateURL* default_provider = model->GetDefaultSearchProvider(); 220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (default_provider && 221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) !default_provider->SupportsReplacement(model->search_terms_data())) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default_provider = NULL; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (keyword_provider == default_provider) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default_provider = NULL; // No use in querying the same provider twice. 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!default_provider && !keyword_provider) { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No valid providers. 229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Stop(true); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we're still running an old query but have since changed the query text 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // or the providers, abort the query. 235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 default_provider_keyword(default_provider ? 236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) default_provider->keyword() : base::string16()); 237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 keyword_provider_keyword(keyword_provider ? 238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) keyword_provider->keyword() : base::string16()); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!minimal_changes || 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !providers_.equal(default_provider_keyword, keyword_provider_keyword)) { 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Cancel any in-flight suggest requests. 242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!done_) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Stop(false); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) providers_.set(default_provider_keyword, keyword_provider_keyword); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (input.text().empty()) { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // User typed "?" alone. Give them a placeholder result indicating what 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this syntax does. 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (default_provider) { 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutocompleteMatch match; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match.provider = this; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match.contents.assign(l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE)); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match.contents_class.push_back( 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ACMatchClassification(0, ACMatchClassification::NONE)); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match.keyword = providers_.default_provider(); 258c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch match.allowed_to_be_default_match = true; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) matches_.push_back(match); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Stop(true); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_ = input; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DoHistoryQuery(minimal_changes); 2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Answers needs scored history results before any suggest query has been 2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // started, since the query for answer-bearing results needs additional 2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // prefetch information based on the highest-scored local history result. 2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (OmniboxFieldTrial::EnableAnswersInSuggest()) { 2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ScoreHistoryResults(raw_default_history_results_, 2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci false, 2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &transformed_default_history_results_); 2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ScoreHistoryResults(raw_keyword_history_results_, 2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci true, 2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &transformed_keyword_history_results_); 2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci prefetch_data_ = FindAnswersPrefetchData(); 2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Raw results are not needed any more. 2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci raw_default_history_results_.clear(); 2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci raw_keyword_history_results_.clear(); 2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transformed_default_history_results_.clear(); 2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transformed_keyword_history_results_.clear(); 2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StartOrStopSuggestQuery(minimal_changes); 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateMatches(); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void SearchProvider::Stop(bool clear_cached_results) { 29303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) StopSuggest(); 29403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) done_ = true; 29503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 29603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (clear_cached_results) 29703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ClearAllResults(); 29803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 29903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 30023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)const TemplateURL* SearchProvider::GetTemplateURL(bool is_keyword) const { 30123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return is_keyword ? providers_.GetKeywordProviderURL() 30223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) : providers_.GetDefaultProviderURL(); 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const AutocompleteInput SearchProvider::GetInput(bool is_keyword) const { 306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return is_keyword ? keyword_input_ : input_; 3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool SearchProvider::ShouldAppendExtraParams( 3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const SearchSuggestionParser::SuggestResult& result) const { 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return !result.from_keyword_provider() || 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) providers_.default_provider().empty(); 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 315a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SearchProvider::RecordDeletionResult(bool success) { 316a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (success) { 3176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::RecordAction( 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UserMetricsAction("Omnibox.ServerSuggestDelete.Success")); 319a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 3206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::RecordAction( 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UserMetricsAction("Omnibox.ServerSuggestDelete.Failure")); 322a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 323a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 3256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void SearchProvider::OnURLFetchComplete(const net::URLFetcher* source) { 3266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(!done_); 3276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) --suggest_results_pending_; 3286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_GE(suggest_results_pending_, 0); // Should never go negative. 3296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const bool is_keyword = source == keyword_fetcher_.get(); 3316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Ensure the request succeeded and that the provider used is still available. 3336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // A verbatim match cannot be generated without this provider, causing errors. 3346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const bool request_succeeded = 3356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) source->GetStatus().is_success() && (source->GetResponseCode() == 200) && 3366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) GetTemplateURL(is_keyword); 3376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) LogFetchComplete(request_succeeded, is_keyword); 3396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool results_updated = false; 3416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (request_succeeded) { 3426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scoped_ptr<base::Value> data(SearchSuggestionParser::DeserializeJsonData( 3436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SearchSuggestionParser::ExtractJsonData(source))); 3446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (data) { 3456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SearchSuggestionParser::Results* results = 3466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) is_keyword ? &keyword_results_ : &default_results_; 3476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) results_updated = ParseSuggestResults(*data, -1, is_keyword, results); 3486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (results_updated) 3496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SortResults(is_keyword, results); 3506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) UpdateMatches(); 3536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (done_ || results_updated) 3546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) listener_->OnProviderUpdate(results_updated); 3556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 3566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 35703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void SearchProvider::StopSuggest() { 35803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Increment the appropriate field in the histogram by the number of 35903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // pending requests that were invalidated. 36003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) for (int i = 0; i < suggest_results_pending_; ++i) 36103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LogOmniboxSuggestRequest(REQUEST_INVALIDATED); 36203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) suggest_results_pending_ = 0; 36303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) timer_.Stop(); 36403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Stop any in-progress URL fetches. 36503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) keyword_fetcher_.reset(); 36603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) default_fetcher_.reset(); 36703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 36803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 36903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void SearchProvider::ClearAllResults() { 37003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) keyword_results_.Clear(); 37103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) default_results_.Clear(); 37203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 37303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 3746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void SearchProvider::UpdateMatchContentsClass( 3756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const base::string16& input_text, 3766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SearchSuggestionParser::Results* results) { 3776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) for (SearchSuggestionParser::SuggestResults::iterator sug_it = 3786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) results->suggest_results.begin(); 3796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) sug_it != results->suggest_results.end(); ++sug_it) { 3806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) sug_it->ClassifyMatchContents(false, input_text); 3816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string languages(client_->AcceptLanguages()); 3836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) for (SearchSuggestionParser::NavigationResults::iterator nav_it = 3846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) results->navigation_results.begin(); 3856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) nav_it != results->navigation_results.end(); ++nav_it) { 3866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) nav_it->CalculateAndClassifyMatchContents(false, input_text, languages); 3876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 3896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void SearchProvider::SortResults(bool is_keyword, 3916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SearchSuggestionParser::Results* results) { 3926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Ignore suggested scores for non-keyword matches in keyword mode; if the 3936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // server is allowed to score these, it could interfere with the user's 3946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // ability to get good keyword results. 3956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const bool abandon_suggested_scores = 3966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) !is_keyword && !providers_.keyword_provider().empty(); 3976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Apply calculated relevance scores to suggestions if valid relevances were 3986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // not provided or we're abandoning suggested scores entirely. 3996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!results->relevances_from_server || abandon_suggested_scores) { 4006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ApplyCalculatedSuggestRelevance(&results->suggest_results); 4016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ApplyCalculatedNavigationRelevance(&results->navigation_results); 4026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // If abandoning scores entirely, also abandon the verbatim score. 4036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (abandon_suggested_scores) 4046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) results->verbatim_relevance = -1; 4056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 4066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Keep the result lists sorted. 4086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const CompareScoredResults comparator = CompareScoredResults(); 4096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::stable_sort(results->suggest_results.begin(), 4106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) results->suggest_results.end(), 4116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) comparator); 4126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::stable_sort(results->navigation_results.begin(), 4136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) results->navigation_results.end(), 4146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) comparator); 4156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 4166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 41723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void SearchProvider::LogFetchComplete(bool success, bool is_keyword) { 41823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) LogOmniboxSuggestRequest(REPLY_RECEIVED); 41923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Record response time for suggest requests sent to Google. We care 42023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // only about the common case: the Google default provider used in 42123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // non-keyword mode. 42223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const TemplateURL* default_url = providers_.GetDefaultProviderURL(); 42323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!is_keyword && default_url && 424f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (TemplateURLPrepopulateData::GetEngineType( 425f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *default_url, 426f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) providers_.template_url_service()->search_terms_data()) == 42723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) SEARCH_ENGINE_GOOGLE)) { 42823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const base::TimeDelta elapsed_time = 42923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) base::TimeTicks::Now() - time_suggest_request_sent_; 43023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (success) { 43123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) UMA_HISTOGRAM_TIMES("Omnibox.SuggestRequest.Success.GoogleResponseTime", 43223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) elapsed_time); 43323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } else { 43423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) UMA_HISTOGRAM_TIMES("Omnibox.SuggestRequest.Failure.GoogleResponseTime", 43523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) elapsed_time); 43623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 43723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 43823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 43923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 44023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void SearchProvider::UpdateMatches() { 4411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PersistTopSuggestions(&default_results_); 4421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PersistTopSuggestions(&keyword_results_); 44323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ConvertResultsToAutocompleteMatches(); 44423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 44523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Check constraints that may be violated by suggested relevances. 44623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!matches_.empty() && 44723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) (default_results_.HasServerProvidedScores() || 44823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) keyword_results_.HasServerProvidedScores())) { 44923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // These blocks attempt to repair undesirable behavior by suggested 45023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // relevances with minimal impact, preserving other suggested relevances. 45123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 45203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); 45303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const bool is_extension_keyword = (keyword_url != NULL) && 45403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) (keyword_url->GetType() == TemplateURL::OMNIBOX_API_EXTENSION); 45503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if ((keyword_url != NULL) && !is_extension_keyword && 4566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) (FindTopMatch() == matches_.end())) { 45703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // In non-extension keyword mode, disregard the keyword verbatim suggested 45803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // relevance if necessary, so at least one match is allowed to be default. 45903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // (In extension keyword mode this is not necessary because the extension 4601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // will return a default match.) Give keyword verbatim the lowest 4611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // non-zero score to best reflect what the server desired. 4621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(0, keyword_results_.verbatim_relevance); 4631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci keyword_results_.verbatim_relevance = 1; 46423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ConvertResultsToAutocompleteMatches(); 46523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 466a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (IsTopMatchSearchWithURLInput()) { 46723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Disregard the suggested search and verbatim relevances if the input 46823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // type is URL and the top match is a highly-ranked search suggestion. 46923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // For example, prevent a search for "foo.com" from outranking another 47023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // provider's navigation for "foo.com" or "foo.com/url_from_history". 47123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ApplyCalculatedSuggestRelevance(&keyword_results_.suggest_results); 47223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ApplyCalculatedSuggestRelevance(&default_results_.suggest_results); 47323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) default_results_.verbatim_relevance = -1; 47423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) keyword_results_.verbatim_relevance = -1; 47523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ConvertResultsToAutocompleteMatches(); 47623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 47703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!is_extension_keyword && (FindTopMatch() == matches_.end())) { 47803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Guarantee that SearchProvider returns a legal default match (except 47903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // when in extension-based keyword mode). The omnibox always needs at 48003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // least one legal default match, and it relies on SearchProvider in 48103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // combination with KeywordProvider (for extension-based keywords) to 4821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // always return one. Give the verbatim suggestion the lowest non-zero 4831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // scores to best reflect what the server desired. 4841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(0, default_results_.verbatim_relevance); 4851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci default_results_.verbatim_relevance = 1; 4861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // We do not have to alter keyword_results_.verbatim_relevance here. 4871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If the user is in keyword mode, we already reverted (earlier in this 4881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // function) the instructions to suppress keyword verbatim. 48923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ConvertResultsToAutocompleteMatches(); 49023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 491a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch DCHECK(!IsTopMatchSearchWithURLInput()); 49203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(is_extension_keyword || (FindTopMatch() != matches_.end())); 49323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 49423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS( 49523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) "Omnibox.SearchProviderMatches", matches_.size(), 1, 6, 7); 4961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Record the top suggestion (if any) for future use. 4981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci top_query_suggestion_match_contents_ = base::string16(); 4991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci top_navigation_suggestion_ = GURL(); 5001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ACMatches::const_iterator first_match = FindTopMatch(); 5011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if ((first_match != matches_.end()) && 5021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci !first_match->inline_autocompletion.empty()) { 5031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Identify if this match came from a query suggestion or a navsuggestion. 5041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // In either case, extracts the identifying feature of the suggestion 5051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // (query string or navigation url). 5061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (AutocompleteMatch::IsSearchType(first_match->type)) 5071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci top_query_suggestion_match_contents_ = first_match->contents; 5081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci else 5091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci top_navigation_suggestion_ = first_match->destination_url; 5101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 51223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) UpdateDone(); 51323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 51423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SearchProvider::Run() { 516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Start a new request with the current input. 517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch suggest_results_pending_ = 0; 518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch time_suggest_request_sent_ = base::TimeTicks::Now(); 519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch default_fetcher_.reset(CreateSuggestFetcher(kDefaultProviderURLFetcherID, 521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch providers_.GetDefaultProviderURL(), input_)); 522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch keyword_fetcher_.reset(CreateSuggestFetcher(kKeywordProviderURLFetcherID, 523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch providers_.GetKeywordProviderURL(), keyword_input_)); 524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Both the above can fail if the providers have been modified or deleted 526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // since the query began. 527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (suggest_results_pending_ == 0) { 528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UpdateDone(); 529eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // We only need to update the listener if we're actually done. 530eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (done_) 531eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch listener_->OnProviderUpdate(false); 532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SearchProvider::DoHistoryQuery(bool minimal_changes) { 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The history query results are synchronous, so if minimal_changes is true, 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we still have the last results and don't need to do anything. 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (minimal_changes) 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci raw_keyword_history_results_.clear(); 5421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci raw_default_history_results_.clear(); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 544a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (OmniboxFieldTrial::SearchHistoryDisable( 545a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) input_.current_page_classification())) 5467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 5477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 5481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci history::URLDatabase* url_db = client_->InMemoryDatabase(); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_db) 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Request history for both the keyword and default provider. We grab many 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // more matches than we'll ultimately clamp to so that if there are several 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // recent multi-word matches who scores are lowered (see 5551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // ScoreHistoryResults()), they won't crowd out older, higher-scoring 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // matches. Note that this doesn't fix the problem entirely, but merely 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // limits it to cases with a very large number of such multi-word matches; for 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // now, this seems OK compared with the complexity of a real fix, which would 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // require multiple searches and tracking of "single- vs. multi-word" in the 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // database. 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_matches = kMaxMatches * 5; 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TemplateURL* default_url = providers_.GetDefaultProviderURL(); 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (default_url) { 564c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const base::TimeTicks start_time = base::TimeTicks::Now(); 5651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url_db->GetMostRecentKeywordSearchTerms(default_url->id(), 5661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci input_.text(), 5671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci num_matches, 5681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &raw_default_history_results_); 56968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) UMA_HISTOGRAM_TIMES( 57068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "Omnibox.SearchProvider.GetMostRecentKeywordTermsDefaultProviderTime", 57168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::TimeTicks::Now() - start_time); 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (keyword_url) { 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_db->GetMostRecentKeywordSearchTerms(keyword_url->id(), 5761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci keyword_input_.text(), 5771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci num_matches, 5781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &raw_keyword_history_results_); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SearchProvider::StartOrStopSuggestQuery(bool minimal_changes) { 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsQuerySuitableForSuggest()) { 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopSuggest(); 585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ClearAllResults(); 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For the minimal_changes case, if we finished the previous query and still 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // have its results, or are allowed to keep running it, just do that, rather 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // than starting a new query. 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (minimal_changes && 59390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (!default_results_.suggest_results.empty() || 59490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) !default_results_.navigation_results.empty() || 59590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) !keyword_results_.suggest_results.empty() || 59690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) !keyword_results_.navigation_results.empty() || 5970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (!done_ && input_.want_asynchronous_matches()))) 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can't keep running any previous query, so halt it. 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopSuggest(); 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UpdateAllOldResults(minimal_changes); 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Update the content classifications of remaining results so they look good 6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // against the current input. 6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UpdateMatchContentsClass(input_.text(), &default_results_); 6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!keyword_input_.text().empty()) 6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UpdateMatchContentsClass(keyword_input_.text(), &keyword_results_); 6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can't start a new query if we're only allowed synchronous results. 6120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!input_.want_asynchronous_matches()) 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // To avoid flooding the suggest server, don't send a query until at 616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // least 100 ms since the last query. 6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks next_suggest_time(time_suggest_request_sent_ + 618eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::TimeDelta::FromMilliseconds(kMinimumTimeBetweenSuggestQueriesMs)); 6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks now(base::TimeTicks::Now()); 6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (now >= next_suggest_time) { 6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Run(); 6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) timer_.Start(FROM_HERE, next_suggest_time - now, this, &SearchProvider::Run); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SearchProvider::IsQuerySuitableForSuggest() const { 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't run Suggest in incognito mode, if the engine doesn't support it, or 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if the user has disabled it. 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TemplateURL* default_url = providers_.GetDefaultProviderURL(); 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); 6321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (client_->IsOffTheRecord() || 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((!default_url || default_url->suggestions_url().empty()) && 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (!keyword_url || keyword_url->suggestions_url().empty())) || 6351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci !client_->SearchSuggestEnabled()) 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the input type might be a URL, we take extra care so that private data 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // isn't sent to the server. 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FORCED_QUERY means the user is explicitly asking us to search for this, so 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we assume it isn't a URL and/or there isn't private data. 643f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (input_.type() == metrics::OmniboxInputType::FORCED_QUERY) 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Next we check the scheme. If this is UNKNOWN/URL with a scheme that isn't 6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // http/https/ftp, we shouldn't send it. Sending things like file: and data: 6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // is both a waste of time and a disclosure of potentially private, local 6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // data. Other "schemes" may actually be usernames, and we don't want to send 6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // passwords. If the scheme is OK, we still need to check other cases below. 6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If this is QUERY, then the presence of these schemes means the user 6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // explicitly typed one, and thus this is probably a URL that's being entered 6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and happens to currently be invalid -- in which case we again want to run 6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // our checks below. Other QUERY cases are less likely to be URLs and thus we 6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // assume we're OK. 656010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!LowerCaseEqualsASCII(input_.scheme(), url::kHttpScheme) && 657010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) !LowerCaseEqualsASCII(input_.scheme(), url::kHttpsScheme) && 658cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) !LowerCaseEqualsASCII(input_.scheme(), url::kFtpScheme)) 659f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return (input_.type() == metrics::OmniboxInputType::QUERY); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't send URLs with usernames, queries or refs. Some of these are 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // private, and the Suggest server is unlikely to have any useful results 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for any of them. Also don't send URLs with ports, as we may initially 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // think that a username + password is a host + port (and we don't want to 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // send usernames/passwords), and even if the port really is a port, the 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // server is once again unlikely to have and useful results. 6674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Note that we only block based on refs if the input is URL-typed, as search 6684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // queries can legitimately have #s in them which the URL parser 6694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // overaggressively categorizes as a url with a ref. 6705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const url::Parsed& parts = input_.parts(); 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parts.username.is_nonempty() || parts.port.is_nonempty() || 6724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) parts.query.is_nonempty() || 673f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (parts.ref.is_nonempty() && 674f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (input_.type() == metrics::OmniboxInputType::URL))) 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't send anything for https except the hostname. Hostnames are OK 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because they are visible when the TCP connection is established, but the 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // specific path may reveal private information. 680010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (LowerCaseEqualsASCII(input_.scheme(), url::kHttpsScheme) && 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parts.path.is_nonempty()) 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SearchProvider::UpdateAllOldResults(bool minimal_changes) { 688f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (keyword_input_.text().empty()) { 689c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // User is either in keyword mode with a blank input or out of 690c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // keyword mode entirely. 69190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) keyword_results_.Clear(); 692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 6931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UpdateOldResults(minimal_changes, &default_results_); 6941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UpdateOldResults(minimal_changes, &keyword_results_); 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SearchProvider::PersistTopSuggestions( 6981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SearchSuggestionParser::Results* results) { 6991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Mark any results matching the current top results as having been received 7001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // prior to the last keystroke. That prevents asynchronous updates from 7011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // clobbering top results, which may be used for inline autocompletion. 7021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Other results don't need similar changes, because they shouldn't be 7031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // displayed asynchronously anyway. 7041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!top_query_suggestion_match_contents_.empty()) { 7051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (SearchSuggestionParser::SuggestResults::iterator sug_it = 7061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci results->suggest_results.begin(); 7071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sug_it != results->suggest_results.end(); ++sug_it) { 7081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (sug_it->match_contents() == top_query_suggestion_match_contents_) 7091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sug_it->set_received_after_last_keystroke(false); 7101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 7111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 7121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (top_navigation_suggestion_.is_valid()) { 7131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (SearchSuggestionParser::NavigationResults::iterator nav_it = 7141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci results->navigation_results.begin(); 7151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci nav_it != results->navigation_results.end(); ++nav_it) { 7161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (nav_it->url() == top_navigation_suggestion_) 7171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci nav_it->set_received_after_last_keystroke(false); 7181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 7191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SearchProvider::ApplyCalculatedSuggestRelevance( 7235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SearchSuggestionParser::SuggestResults* list) { 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < list->size(); ++i) { 7255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SearchSuggestionParser::SuggestResult& result = (*list)[i]; 726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.set_relevance( 727c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.CalculateRelevance(input_, providers_.has_keyword_provider()) + 728c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (list->size() - i - 1)); 729eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result.set_relevance_from_server(false); 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 733c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SearchProvider::ApplyCalculatedNavigationRelevance( 7345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SearchSuggestionParser::NavigationResults* list) { 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < list->size(); ++i) { 7365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SearchSuggestionParser::NavigationResult& result = (*list)[i]; 737c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.set_relevance( 738c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.CalculateRelevance(input_, providers_.has_keyword_provider()) + 739c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (list->size() - i - 1)); 740eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result.set_relevance_from_server(false); 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)net::URLFetcher* SearchProvider::CreateSuggestFetcher( 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int id, 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TemplateURL* template_url, 7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const AutocompleteInput& input) { 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!template_url || template_url->suggestions_url().empty()) 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Bail if the suggestion URL is invalid with the given replacements. 7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TemplateURLRef::SearchTermsArgs search_term_args(input.text()); 753f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) search_term_args.input_type = input.type(); 7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) search_term_args.cursor_position = input.cursor_position(); 755ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch search_term_args.page_classification = input.current_page_classification(); 7565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (OmniboxFieldTrial::EnableAnswersInSuggest()) { 757cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) search_term_args.session_token = GetSessionToken(); 7585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!prefetch_data_.full_query_text.empty()) { 7595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) search_term_args.prefetch_query = 76003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::UTF16ToUTF8(prefetch_data_.full_query_text); 7615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) search_term_args.prefetch_query_type = 76203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::UTF16ToUTF8(prefetch_data_.query_type); 7635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 7645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL suggest_url(template_url->suggestions_url_ref().ReplaceSearchTerms( 766f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) search_term_args, 767f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) providers_.template_url_service()->search_terms_data())); 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!suggest_url.is_valid()) 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 770f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Send the current page URL if user setting and URL requirements are met and 771f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // the user is in the field trial. 772f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (CanSendURL(current_page_url_, suggest_url, template_url, 7735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) input.current_page_classification(), 7741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci template_url_service_->search_terms_data(), client_.get()) && 775f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) OmniboxFieldTrial::InZeroSuggestAfterTypingFieldTrial()) { 776f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) search_term_args.current_page_url = current_page_url_.spec(); 777f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Create the suggest URL again with the current page URL. 778f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) suggest_url = GURL(template_url->suggestions_url_ref().ReplaceSearchTerms( 779f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) search_term_args, 780f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) providers_.template_url_service()->search_terms_data())); 781f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suggest_results_pending_++; 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogOmniboxSuggestRequest(REQUEST_SENT); 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLFetcher* fetcher = 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLFetcher::Create(id, suggest_url, net::URLFetcher::GET, this); 7881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci fetcher->SetRequestContext(client_->RequestContext()); 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES); 7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Add Chrome experiment state to the request headers. 7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::HttpRequestHeaders headers; 792116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders( 7931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci fetcher->GetOriginalURL(), client_->IsOffTheRecord(), false, &headers); 7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher->SetExtraRequestHeaders(headers.ToString()); 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->Start(); 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return fetcher; 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SearchProvider::ConvertResultsToAutocompleteMatches() { 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Convert all the results to matches and add them to a map, so we can keep 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the most relevant match for each result. 80268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::TimeTicks start_time(base::TimeTicks::Now()); 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MatchMap map; 804eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::Time no_time; 80590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int did_not_accept_keyword_suggestion = 80690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) keyword_results_.suggest_results.empty() ? 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLRef::NO_SUGGESTION_CHOSEN; 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 810eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool relevance_from_server; 811eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int verbatim_relevance = GetVerbatimRelevance(&relevance_from_server); 81290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int did_not_accept_default_suggestion = 81390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) default_results_.suggest_results.empty() ? 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLRef::NO_SUGGESTION_CHOSEN; 8166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (verbatim_relevance > 0) { 818effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const base::string16& trimmed_verbatim = 819effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::CollapseWhitespace(input_.text(), false); 8206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 8216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Verbatim results don't get suggestions and hence, answers. 8226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Scan previous matches if the last answer-bearing suggestion matches 8236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // verbatim, and if so, copy over answer contents. 8246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::string16 answer_contents; 8256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::string16 answer_type; 8266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) for (ACMatches::iterator it = matches_.begin(); it != matches_.end(); 8276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ++it) { 8286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!it->answer_contents.empty() && 8296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) it->fill_into_edit == trimmed_verbatim) { 8306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) answer_contents = it->answer_contents; 8316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) answer_type = it->answer_type; 8326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) break; 8336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 8346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 8356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 8365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SearchSuggestionParser::SuggestResult verbatim( 837effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch trimmed_verbatim, AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, 8386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) trimmed_verbatim, base::string16(), base::string16(), answer_contents, 8396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) answer_type, std::string(), std::string(), false, verbatim_relevance, 8406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) relevance_from_server, false, trimmed_verbatim); 841a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AddMatchToMap(verbatim, std::string(), did_not_accept_default_suggestion, 8426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) false, keyword_url != NULL, &map); 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!keyword_input_.text().empty()) { 8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We only create the verbatim search query match for a keyword 8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // if it's not an extension keyword. Extension keywords are handled 8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // in KeywordProvider::Start(). (Extensions are complicated...) 8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Note: in this provider, SEARCH_OTHER_ENGINE must correspond 8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to the keyword verbatim search query. Do not create other matches 8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // of type SEARCH_OTHER_ENGINE. 8511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (keyword_url && 8521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) (keyword_url->GetType() != TemplateURL::OMNIBOX_API_EXTENSION)) { 853eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool keyword_relevance_from_server; 854eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const int keyword_verbatim_relevance = 855eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GetKeywordVerbatimRelevance(&keyword_relevance_from_server); 8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (keyword_verbatim_relevance > 0) { 857effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const base::string16& trimmed_verbatim = 858effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::CollapseWhitespace(keyword_input_.text(), false); 8595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SearchSuggestionParser::SuggestResult verbatim( 860effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch trimmed_verbatim, AutocompleteMatchType::SEARCH_OTHER_ENGINE, 861effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch trimmed_verbatim, base::string16(), base::string16(), 862cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::string16(), base::string16(), std::string(), std::string(), 863cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) true, keyword_verbatim_relevance, keyword_relevance_from_server, 864cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) false, trimmed_verbatim); 865a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AddMatchToMap(verbatim, std::string(), 8666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) did_not_accept_keyword_suggestion, false, true, &map); 8672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddRawHistoryResultsToMap(true, did_not_accept_keyword_suggestion, &map); 8711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddRawHistoryResultsToMap(false, did_not_accept_default_suggestion, &map); 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 873d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AddSuggestResultsToMap(keyword_results_.suggest_results, 874d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) keyword_results_.metadata, &map); 875424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) AddSuggestResultsToMap(default_results_.suggest_results, 876424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) default_results_.metadata, &map); 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 878eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ACMatches matches; 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (MatchMap::const_iterator i(map.begin()); i != map.end(); ++i) 880eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch matches.push_back(i->second); 881eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 882eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddNavigationResultsToMatches(keyword_results_.navigation_results, &matches); 883eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddNavigationResultsToMatches(default_results_.navigation_results, &matches); 884eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 885eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Now add the most relevant matches to |matches_|. We take up to kMaxMatches 8861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // suggest/navsuggest matches, regardless of origin. We always include in 8871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // that set a legal default match if possible. If Instant Extended is enabled 8881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // and we have server-provided (and thus hopefully more accurate) scores for 8891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // some suggestions, we allow more of those, until we reach 890eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // AutocompleteResult::kMaxMatches total matches (that is, enough to fill the 891eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // whole popup). 892eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // 893eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // We will always return any verbatim matches, no matter how we obtained their 894eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // scores, unless we have already accepted AutocompleteResult::kMaxMatches 895eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // higher-scoring matches under the conditions above. 896eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::sort(matches.begin(), matches.end(), &AutocompleteMatch::MoreRelevant); 897eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 8981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Guarantee that if there's a legal default match anywhere in the result 8991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // set that it'll get returned. The rotate() call does this by moving the 9001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // default match to the front of the list. 9011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ACMatches::iterator default_match = FindTopMatch(&matches); 9021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (default_match != matches.end()) 9031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::rotate(matches.begin(), default_match, default_match + 1); 9041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 9051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // It's possible to get a copy of an answer from previous matches and get the 9061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // same or a different answer to another server-provided suggestion. In the 9071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // future we may decide that we want to have answers attached to multiple 9081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // suggestions, but the current assumption is that there should only ever be 9091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // one suggestion with an answer. To maintain this assumption, remove any 9101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // answers after the first. 9111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RemoveExtraAnswers(&matches); 9121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 9131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci matches_.clear(); 914eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch size_t num_suggestions = 0; 915eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (ACMatches::const_iterator i(matches.begin()); 916eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (i != matches.end()) && 917eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (matches_.size() < AutocompleteResult::kMaxMatches); 918eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ++i) { 919eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // SEARCH_OTHER_ENGINE is only used in the SearchProvider for the keyword 920eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // verbatim result, so this condition basically means "if this match is a 921eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // suggestion of some sort". 922eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if ((i->type != AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED) && 923eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (i->type != AutocompleteMatchType::SEARCH_OTHER_ENGINE)) { 924eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // If we've already hit the limit on non-server-scored suggestions, and 925eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // this isn't a server-scored suggestion we can add, skip it. 926eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if ((num_suggestions >= kMaxMatches) && 927eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (!chrome::IsInstantExtendedAPIEnabled() || 928eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (i->GetAdditionalInfo(kRelevanceFromServerKey) != kTrue))) { 929eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch continue; 930eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 932eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ++num_suggestions; 933eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch matches_.push_back(*i); 936eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 93768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.ConvertResultsTime", 93868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::TimeTicks::Now() - start_time); 9392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SearchProvider::RemoveExtraAnswers(ACMatches* matches) { 9421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool answer_seen = false; 9431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (ACMatches::iterator it = matches->begin(); it != matches->end(); ++it) { 9441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!it->answer_contents.empty()) { 9451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!answer_seen) { 9461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci answer_seen = true; 9471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 9481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci it->answer_contents.clear(); 9491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci it->answer_type.clear(); 9501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 9511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 9521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 9531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 9541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 955a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochACMatches::const_iterator SearchProvider::FindTopMatch() const { 956f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ACMatches::const_iterator it = matches_.begin(); 957f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) while ((it != matches_.end()) && !it->allowed_to_be_default_match) 958f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ++it; 959f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return it; 960f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 961f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 962a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochbool SearchProvider::IsTopMatchSearchWithURLInput() const { 963a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch ACMatches::const_iterator first_match = FindTopMatch(); 964f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return (input_.type() == metrics::OmniboxInputType::URL) && 965f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) (first_match != matches_.end()) && 966f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) (first_match->relevance > CalculateRelevanceForVerbatim()) && 967010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) (first_match->type != AutocompleteMatchType::NAVSUGGEST) && 968010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) (first_match->type != AutocompleteMatchType::NAVSUGGEST_PERSONALIZED); 9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SearchProvider::AddNavigationResultsToMatches( 9725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const SearchSuggestionParser::NavigationResults& navigation_results, 973eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ACMatches* matches) { 9745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (SearchSuggestionParser::NavigationResults::const_iterator it = 9755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) navigation_results.begin(); it != navigation_results.end(); ++it) { 976eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch matches->push_back(NavigationToMatch(*it)); 977eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // In the absence of suggested relevance scores, use only the single 978eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // highest-scoring result. (The results are already sorted by relevance.) 979eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!it->relevance_from_server()) 980eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SearchProvider::AddRawHistoryResultsToMap(bool is_keyword, 9851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int did_not_accept_suggestion, 9861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MatchMap* map) { 9871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const HistoryResults& raw_results = 9881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci is_keyword ? raw_keyword_history_results_ : raw_default_history_results_; 9891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!OmniboxFieldTrial::EnableAnswersInSuggest() && raw_results.empty()) 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 99268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::TimeTicks start_time(base::TimeTicks::Now()); 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Until Answers becomes default, scoring of history results will still happen 9951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // here for non-Answers Chrome, to prevent scoring performance regressions 9961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // resulting from moving the scoring code before the suggest request is sent. 9971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // For users with Answers enabled, the history results have already been 9981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // scored earlier, right after calling DoHistoryQuery(). 9991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SearchSuggestionParser::SuggestResults local_transformed_results; 10001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const SearchSuggestionParser::SuggestResults* transformed_results = NULL; 10011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!OmniboxFieldTrial::EnableAnswersInSuggest()) { 10021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ScoreHistoryResults(raw_results, is_keyword, &local_transformed_results); 10031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transformed_results = &local_transformed_results; 10041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 10051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transformed_results = is_keyword ? &transformed_keyword_history_results_ 10061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : &transformed_default_history_results_; 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(transformed_results); 10091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddTransformedHistoryResultsToMap( 10101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *transformed_results, did_not_accept_suggestion, map); 10111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.AddHistoryResultsTime", 10121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::TimeTicks::Now() - start_time); 10131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 10141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 10151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SearchProvider::AddTransformedHistoryResultsToMap( 10161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const SearchSuggestionParser::SuggestResults& transformed_results, 10171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int did_not_accept_suggestion, 10181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MatchMap* map) { 10195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (SearchSuggestionParser::SuggestResults::const_iterator i( 10201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transformed_results.begin()); 10211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci i != transformed_results.end(); 10221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++i) { 10236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) AddMatchToMap(*i, std::string(), did_not_accept_suggestion, true, 10246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) providers_.GetKeywordProviderURL() != NULL, map); 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciSearchSuggestionParser::SuggestResults 10291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciSearchProvider::ScoreHistoryResultsHelper(const HistoryResults& results, 10301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool base_prevent_inline_autocomplete, 10311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool input_multiple_words, 10321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const base::string16& input_text, 10331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool is_keyword) { 10345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SearchSuggestionParser::SuggestResults scored_results; 1035116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // True if the user has asked this exact query previously. 1036116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool found_what_you_typed_match = false; 1037a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const bool prevent_search_history_inlining = 1038a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) OmniboxFieldTrial::SearchHistoryPreventInlining( 1039a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) input_.current_page_classification()); 1040effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const base::string16& trimmed_input = 1041effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::CollapseWhitespace(input_text, false); 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (HistoryResults::const_iterator i(results.begin()); i != results.end(); 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i) { 1044effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const base::string16& trimmed_suggestion = 1045effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::CollapseWhitespace(i->term, false); 1046effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't autocomplete multi-word queries that have only been seen once 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unless the user has typed more than one word. 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool prevent_inline_autocomplete = base_prevent_inline_autocomplete || 1050effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch (!input_multiple_words && (i->visits < 2) && 1051effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch HasMultipleWords(trimmed_suggestion)); 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1053a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) int relevance = CalculateRelevanceForHistory( 1054a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) i->time, is_keyword, !prevent_inline_autocomplete, 1055a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) prevent_search_history_inlining); 1056116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Add the match to |scored_results| by putting the what-you-typed match 1057116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // on the front and appending all other matches. We want the what-you- 1058116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // typed match to always be first. 10595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SearchSuggestionParser::SuggestResults::iterator insertion_position = 10605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scored_results.end(); 1061116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (trimmed_suggestion == trimmed_input) { 1062116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch found_what_you_typed_match = true; 1063116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch insertion_position = scored_results.begin(); 1064116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 10651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SearchSuggestionParser::SuggestResult history_suggestion( 10661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci trimmed_suggestion, AutocompleteMatchType::SEARCH_HISTORY, 10671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci trimmed_suggestion, base::string16(), base::string16(), 10681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::string16(), base::string16(), std::string(), std::string(), 10691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci is_keyword, relevance, false, false, trimmed_input); 10701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // History results are synchronous; they are received on the last keystroke. 10711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci history_suggestion.set_received_after_last_keystroke(false); 10721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scored_results.insert(insertion_position, history_suggestion); 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // History returns results sorted for us. However, we may have docked some 1076116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // results' scores, so things are no longer in order. While keeping the 1077116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // what-you-typed match at the front (if it exists), do a stable sort to get 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // things back in order without otherwise disturbing results with equal 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // scores, then force the scores to be unique, so that the order in which 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // they're shown is deterministic. 1081116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::stable_sort(scored_results.begin() + 1082116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch (found_what_you_typed_match ? 1 : 0), 1083116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scored_results.end(), 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompareScoredResults()); 10855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 10865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Don't autocomplete to search terms that would normally be treated as URLs 10875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // when typed. For example, if the user searched for "google.com" and types 10885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // "goog", don't autocomplete to the search term "google.com". Otherwise, 10895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // the input will look like a URL but act like a search, which is confusing. 10905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The 1200 relevance score threshold in the test below is the lowest 10915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // possible score in CalculateRelevanceForHistory()'s aggressive-scoring 10925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // curve. This is an appropriate threshold to use to decide if we're overly 10935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // aggressively inlining because, if we decide the answer is yes, the 10945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // way we resolve it it to not use the aggressive-scoring curve. 10955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // NOTE: We don't check for autocompleting to URLs in the following cases: 10965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // * When inline autocomplete is disabled, we won't be inline autocompleting 10975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // this term, so we don't need to worry about confusion as much. This 10985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // also prevents calling Classify() again from inside the classifier 10995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // (which will corrupt state and likely crash), since the classifier 11005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // always disables inline autocomplete. 11015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // * When the user has typed the whole string before as a query, then it's 11025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // likely the user has no expectation that term should be interpreted as 11035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // as a URL, so we need not do anything special to preserve user 11045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // expectation. 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int last_relevance = 0; 11065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!base_prevent_inline_autocomplete && !found_what_you_typed_match && 11071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scored_results.front().relevance() >= 1200) { 11085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) AutocompleteMatch match; 11091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci client_->Classify(scored_results.front().suggestion(), false, false, 11101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci input_.current_page_classification(), &match, NULL); 11115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Demote this match that would normally be interpreted as a URL to have 11125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // the highest score a previously-issued search query could have when 11135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // scoring with the non-aggressive method. A consequence of demoting 11145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // by revising |last_relevance| is that this match and all following 11155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // matches get demoted; the relative order of matches is preserved. 11165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // One could imagine demoting only those matches that might cause 11175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // confusion (which, by the way, might change the relative order of 11185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // matches. We have decided to go with the simple demote-all approach 11195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // because selective demotion requires multiple Classify() calls and 11205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // such calls can be expensive (as expensive as running the whole 11215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // autocomplete system). 11225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!AutocompleteMatch::IsSearchType(match.type)) { 11235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_relevance = CalculateRelevanceForHistory( 11245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Time::Now(), is_keyword, false, 11255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) prevent_search_history_inlining); 11265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 11275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 11285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (SearchSuggestionParser::SuggestResults::iterator i( 11305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scored_results.begin()); i != scored_results.end(); ++i) { 11315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if ((last_relevance != 0) && (i->relevance() >= last_relevance)) 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i->set_relevance(last_relevance - 1); 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_relevance = i->relevance(); 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scored_results; 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SearchProvider::ScoreHistoryResults( 11401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const HistoryResults& results, 11411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool is_keyword, 11421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SearchSuggestionParser::SuggestResults* scored_results) { 11431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(scored_results); 11441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (results.empty()) { 11451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scored_results->clear(); 11461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 11471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 11481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 11491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool prevent_inline_autocomplete = input_.prevent_inline_autocomplete() || 11501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (input_.type() == metrics::OmniboxInputType::URL); 11511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const base::string16 input_text = GetInput(is_keyword).text(); 11521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool input_multiple_words = HasMultipleWords(input_text); 11531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 11541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!prevent_inline_autocomplete && input_multiple_words) { 11551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // ScoreHistoryResultsHelper() allows autocompletion of multi-word, 1-visit 11561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // queries if the input also has multiple words. But if we were already 11571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // scoring a multi-word, multi-visit query aggressively, and the current 11581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // input is still a prefix of it, then changing the suggestion suddenly 11591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // feels wrong. To detect this case, first score as if only one word has 11601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // been typed, then check if the best result came from aggressive search 11611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // history scoring. If it did, then just keep that score set. This 11621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // 1200 the lowest possible score in CalculateRelevanceForHistory()'s 11631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // aggressive-scoring curve. 11641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *scored_results = ScoreHistoryResultsHelper( 11651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci results, prevent_inline_autocomplete, false, input_text, is_keyword); 11661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if ((scored_results->front().relevance() < 1200) || 11671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci !HasMultipleWords(scored_results->front().suggestion())) 11681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scored_results->clear(); // Didn't detect the case above, score normally. 11691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 11701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (scored_results->empty()) { 11711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *scored_results = ScoreHistoryResultsHelper(results, 11721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci prevent_inline_autocomplete, 11731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci input_multiple_words, 11741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci input_text, 11751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci is_keyword); 11761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 11771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 11781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 11795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SearchProvider::AddSuggestResultsToMap( 11805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const SearchSuggestionParser::SuggestResults& results, 11815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& metadata, 11825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MatchMap* map) { 11836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) for (size_t i = 0; i < results.size(); ++i) { 11846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) AddMatchToMap(results[i], metadata, i, false, 11856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) providers_.GetKeywordProviderURL() != NULL, map); 11866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint SearchProvider::GetVerbatimRelevance(bool* relevance_from_server) const { 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use the suggested verbatim relevance score if it is non-negative (valid), 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if inline autocomplete isn't prevented (always show verbatim on backspace), 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and if it won't suppress verbatim, leaving no default provider matches. 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Otherwise, if the default provider returned no matches and was still able 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to suppress verbatim, the user would have no search/nav matches and may be 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // left unable to search using their default provider from the omnibox. 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for results on each verbatim calculation, as results from older 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // queries (on previous input) may be trimmed for failing to inline new input. 1198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool use_server_relevance = 1199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (default_results_.verbatim_relevance >= 0) && 12002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !input_.prevent_inline_autocomplete() && 1201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ((default_results_.verbatim_relevance > 0) || 120290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) !default_results_.suggest_results.empty() || 1203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch !default_results_.navigation_results.empty()); 1204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (relevance_from_server) 1205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *relevance_from_server = use_server_relevance; 1206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return use_server_relevance ? 1207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch default_results_.verbatim_relevance : CalculateRelevanceForVerbatim(); 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SearchProvider::CalculateRelevanceForVerbatim() const { 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!providers_.keyword_provider().empty()) 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 250; 12132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return CalculateRelevanceForVerbatimIgnoringKeywordModeState(); 12142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int SearchProvider:: 12172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CalculateRelevanceForVerbatimIgnoringKeywordModeState() const { 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (input_.type()) { 1219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case metrics::OmniboxInputType::UNKNOWN: 1220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case metrics::OmniboxInputType::QUERY: 1221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case metrics::OmniboxInputType::FORCED_QUERY: 12222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kNonURLVerbatimRelevance; 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case metrics::OmniboxInputType::URL: 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 850; 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint SearchProvider::GetKeywordVerbatimRelevance( 1234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool* relevance_from_server) const { 12352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Use the suggested verbatim relevance score if it is non-negative (valid), 12362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // if inline autocomplete isn't prevented (always show verbatim on backspace), 12372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and if it won't suppress verbatim, leaving no keyword provider matches. 12382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Otherwise, if the keyword provider returned no matches and was still able 12392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to suppress verbatim, the user would have no search/nav matches and may be 12402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // left unable to search using their keyword provider from the omnibox. 12412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check for results on each verbatim calculation, as results from older 12422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // queries (on previous input) may be trimmed for failing to inline new input. 1243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool use_server_relevance = 1244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (keyword_results_.verbatim_relevance >= 0) && 12452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !input_.prevent_inline_autocomplete() && 1246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ((keyword_results_.verbatim_relevance > 0) || 124790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) !keyword_results_.suggest_results.empty() || 1248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch !keyword_results_.navigation_results.empty()); 1249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (relevance_from_server) 1250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *relevance_from_server = use_server_relevance; 1251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return use_server_relevance ? 1252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch keyword_results_.verbatim_relevance : 1253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CalculateRelevanceForKeywordVerbatim(keyword_input_.type(), 1254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch keyword_input_.prefer_keyword()); 12552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 12562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SearchProvider::CalculateRelevanceForHistory( 1258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::Time& time, 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_keyword, 1260a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) bool use_aggressive_method, 1261a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) bool prevent_search_history_inlining) const { 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The relevance of past searches falls off over time. There are two distinct 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // equations used. If the first equation is used (searches to the primary 1264a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // provider that we want to score aggressively), the score is in the range 1265a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // 1300-1599 (unless |prevent_search_history_inlining|, in which case 12667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // it's in the range 1200-1299). If the second equation is used the 12677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // relevance of a search 15 minutes ago is discounted 50 points, while the 12687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // relevance of a search two weeks ago is discounted 450 points. 1269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch double elapsed_time = std::max((base::Time::Now() - time).InSecondsF(), 0.0); 1270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool is_primary_provider = is_keyword || !providers_.has_keyword_provider(); 1271a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (is_primary_provider && use_aggressive_method) { 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Searches with the past two days get a different curve. 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const double autocomplete_time = 2 * 24 * 60 * 60; 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (elapsed_time < autocomplete_time) { 12757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int max_score = is_keyword ? 1599 : 1399; 1276a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (prevent_search_history_inlining) 12777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch max_score = 1299; 12787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return max_score - static_cast<int>(99 * 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pow(elapsed_time / autocomplete_time, 2.5)); 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elapsed_time -= autocomplete_time; 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int score_discount = 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(6.5 * std::pow(elapsed_time, 0.3)); 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't let scores go below 0. Negative relevance scores are meaningful in 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a different way. 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int base_score; 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_primary_provider) 1291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base_score = (input_.type() == metrics::OmniboxInputType::URL) ? 750 : 1050; 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base_score = 200; 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::max(0, base_score - score_discount); 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AutocompleteMatch SearchProvider::NavigationToMatch( 12985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const SearchSuggestionParser::NavigationResult& navigation) { 129923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) base::string16 input; 130023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const bool trimmed_whitespace = base::TrimWhitespace( 130123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) navigation.from_keyword_provider() ? 130223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) keyword_input_.text() : input_.text(), 130323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) base::TRIM_TRAILING, &input) != base::TRIM_NONE; 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutocompleteMatch match(this, navigation.relevance(), false, 1305010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) navigation.type()); 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match.destination_url = navigation.url(); 1307010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) BaseSearchProvider::SetDeletionURL(navigation.deletion_url(), &match); 13085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // First look for the user's input inside the formatted url as it would be 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // without trimming the scheme, so we can find matches at the beginning of the 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // scheme. 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const URLPrefix* prefix = 13125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) URLPrefix::BestURLPrefix(navigation.formatted_url(), input); 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t match_start = (prefix == NULL) ? 13145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) navigation.formatted_url().find(input) : prefix->prefix.length(); 13150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) bool trim_http = !AutocompleteInput::HasHTTPScheme(input) && 13160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) (!prefix || (match_start != 0)); 13175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const net::FormatUrlTypes format_types = 13185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP); 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string languages(client_->AcceptLanguages()); 13215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t inline_autocomplete_offset = (prefix == NULL) ? 13225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16::npos : (match_start + input.length()); 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match.fill_into_edit += 1324116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch AutocompleteInput::FormattedStringWithEquivalentMeaning( 1325116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch navigation.url(), 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::FormatUrl(navigation.url(), languages, format_types, 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::UnescapeRule::SPACES, NULL, NULL, 1328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &inline_autocomplete_offset), 13291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci client_->SchemeClassifier()); 1330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Preserve the forced query '?' prefix in |match.fill_into_edit|. 1331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Otherwise, user edits to a suggestion would show non-Search results. 1332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (input_.type() == metrics::OmniboxInputType::FORCED_QUERY) { 13335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) match.fill_into_edit.insert(0, base::ASCIIToUTF16("?")); 1334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (inline_autocomplete_offset != base::string16::npos) 1335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ++inline_autocomplete_offset; 1336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1337a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (inline_autocomplete_offset != base::string16::npos) { 1338ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length()); 1339ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch match.inline_autocompletion = 1340ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch match.fill_into_edit.substr(inline_autocomplete_offset); 1341ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1342a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // An inlineable navsuggestion can only be the default match when there 1343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // is no keyword provider active, lest it appear first and break the user 13441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // out of keyword mode. We also must have received the navsuggestion before 13451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the last keystroke, to prevent asynchronous inline autocompletions changes. 13461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The navsuggestion can also only be default if either the inline 134723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // autocompletion is empty or we're not preventing inline autocompletion. 134823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Finally, if we have an inlineable navsuggestion with an inline completion 134923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // that we're not preventing, make sure we didn't trim any whitespace. 135023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // We don't want to claim http://foo.com/bar is inlineable against the 135123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // input "foo.com/b ". 13521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci match.allowed_to_be_default_match = 13531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (prefix != NULL) && 1354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (providers_.GetKeywordProviderURL() == NULL) && 13551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci !navigation.received_after_last_keystroke() && 135623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) (match.inline_autocompletion.empty() || 1357010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) (!input_.prevent_inline_autocomplete() && !trimmed_whitespace)); 1358116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch match.EnsureUWYTIsAllowedToBeDefault( 1359116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch input_.canonicalized_url(), providers_.template_url_service()); 13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) match.contents = navigation.match_contents(); 13625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) match.contents_class = navigation.match_contents_class(); 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match.description = navigation.description(); 13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutocompleteMatch::ClassifyMatchInString(input, match.description, 13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ACMatchClassification::NONE, &match.description_class); 1366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch match.RecordAdditionalInfo( 1368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kRelevanceFromServerKey, 1369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch navigation.relevance_from_server() ? kTrue : kFalse); 1370424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) match.RecordAdditionalInfo(kShouldPrefetchKey, kFalse); 1371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return match; 13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SearchProvider::UpdateDone() { 13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We're done when the timer isn't running, there are no suggest queries 13772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // pending, and we're not waiting on Instant. 1378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch done_ = !timer_.IsRunning() && (suggest_results_pending_ == 0); 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)std::string SearchProvider::GetSessionToken() { 1382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::TimeTicks current_time(base::TimeTicks::Now()); 1383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Renew token if it expired. 1384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (current_time > token_expiration_time_) { 1385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const size_t kTokenBytes = 12; 1386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string raw_data; 1387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::RandBytes(WriteInto(&raw_data, kTokenBytes + 1), kTokenBytes); 1388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Base64Encode(raw_data, ¤t_token_); 1389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Make the base64 encoded value URL and filename safe(see RFC 3548). 1391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::replace(current_token_.begin(), current_token_.end(), '+', '-'); 1392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::replace(current_token_.begin(), current_token_.end(), '/', '_'); 1393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 1394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Extend expiration time another 60 seconds. 1396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) token_expiration_time_ = current_time + base::TimeDelta::FromSeconds(60); 1397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return current_token_; 1399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 14005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 14015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SearchProvider::RegisterDisplayedAnswers( 14025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const AutocompleteResult& result) { 14035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (result.empty()) 14045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 14055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 14065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The answer must be in the first or second slot to be considered. It should 14075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // only be in the second slot if AutocompleteController ranked a local search 14085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // history or a verbatim item higher than the answer. 14095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) AutocompleteResult::const_iterator match = result.begin(); 14105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (match->answer_contents.empty() && result.size() > 1) 14115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ++match; 14125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (match->answer_contents.empty() || match->answer_type.empty() || 14135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) match->fill_into_edit.empty()) 14145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 14155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 14165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Valid answer encountered, cache it for further queries. 141703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) answers_cache_.UpdateRecentAnswers(match->fill_into_edit, match->answer_type); 14185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 14195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 14201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciAnswersQueryData SearchProvider::FindAnswersPrefetchData() { 14211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Retrieve the top entry from scored history results. 14221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MatchMap map; 14231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddTransformedHistoryResultsToMap(transformed_keyword_history_results_, 14241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, 14251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &map); 14261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddTransformedHistoryResultsToMap(transformed_default_history_results_, 14271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, 14281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &map); 14291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 14301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ACMatches matches; 14311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (MatchMap::const_iterator i(map.begin()); i != map.end(); ++i) 14321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci matches.push_back(i->second); 14331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::sort(matches.begin(), matches.end(), &AutocompleteMatch::MoreRelevant); 14341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 14351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If there is a top scoring entry, find the corresponding answer. 14361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!matches.empty()) 14371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return answers_cache_.GetTopAnswerEntry(matches[0].contents); 14381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 14391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return AnswersQueryData(); 14405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1441