diff options
author | dominich@chromium.org <dominich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-01 06:16:52 +0000 |
---|---|---|
committer | dominich@chromium.org <dominich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-01 06:16:52 +0000 |
commit | 925136821950cb844c98dcfa88c7807e8708746e (patch) | |
tree | 4b2337cac69fee8f562b68fba7385349f5de0045 /chrome/browser | |
parent | 70213de441a0c8e29ffc6f73bd64c78aabba06aa (diff) | |
download | chromium_src-925136821950cb844c98dcfa88c7807e8708746e.zip chromium_src-925136821950cb844c98dcfa88c7807e8708746e.tar.gz chromium_src-925136821950cb844c98dcfa88c7807e8708746e.tar.bz2 |
Remove confidence from AutocompleteMatch and use History DB instead.
Adds a class responsible for providing recommended actions given an AutocompleteMatch which uses the History Database to determine that action.
BUG=92896,94423
TEST=NetworkActionPredictorTest*
Review URL: http://codereview.chromium.org/7686012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@99140 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
23 files changed, 329 insertions, 271 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_edit.cc b/chrome/browser/autocomplete/autocomplete_edit.cc index ee32f9b..99bc515 100644 --- a/chrome/browser/autocomplete/autocomplete_edit.cc +++ b/chrome/browser/autocomplete/autocomplete_edit.cc @@ -41,53 +41,6 @@ #include "googleurl/src/url_util.h" #include "third_party/skia/include/core/SkBitmap.h" -namespace { - -enum PredictAction { - PREDICT_ACTION_INSTANT = 0, - PREDICT_ACTION_PRERENDER, - PREDICT_ACTION_PRECONNECT, - PREDICT_ACTION_NONE, - LAST_PREDICT_ACTION = PREDICT_ACTION_NONE -}; - -// Given a match, return a recommended action. -PredictAction RecommendPredictAction(const AutocompleteMatch& match) { - // TODO(dominich): These numbers are not final and should be tweaked as - // confidence calculation is finalized. - static const float kConfidenceCutoff[LAST_PREDICT_ACTION] = { - 0.99f, - 0.90f, - 0.10f - }; - - for (int i = 0; i < LAST_PREDICT_ACTION; ++i) - if (match.confidence >= kConfidenceCutoff[i]) - return static_cast<PredictAction>(i); - return PREDICT_ACTION_NONE; -} - -// Return true if the suggestion type warrants a TCP/IP preconnection. -// i.e., it is now quite likely that the user will select the related domain. -bool IsPreconnectable(AutocompleteMatch::Type type) { - UMA_HISTOGRAM_ENUMERATION("Autocomplete.MatchType", type, - AutocompleteMatch::NUM_TYPES); - switch (type) { - // Matches using the user's default search engine. - case AutocompleteMatch::SEARCH_WHAT_YOU_TYPED: - case AutocompleteMatch::SEARCH_HISTORY: - case AutocompleteMatch::SEARCH_SUGGEST: - // A match that uses a non-default search engine (e.g. for tab-to-search). - case AutocompleteMatch::SEARCH_OTHER_ENGINE: - return true; - - default: - return false; - } -} - -} // end namespace - /////////////////////////////////////////////////////////////////////////////// // AutocompleteEditController @@ -132,7 +85,8 @@ AutocompleteEditModel::AutocompleteEditModel( profile_(profile), in_revert_(false), allow_exact_keyword_match_(false), - instant_complete_behavior_(INSTANT_COMPLETE_DELAYED) { + instant_complete_behavior_(INSTANT_COMPLETE_DELAYED), + network_action_predictor_(profile) { } AutocompleteEditModel::~AutocompleteEditModel() { @@ -254,40 +208,33 @@ bool AutocompleteEditModel::AcceptCurrentInstantPreview() { void AutocompleteEditModel::OnChanged() { const AutocompleteMatch current_match = CurrentMatch(); - UMA_HISTOGRAM_COUNTS_100("Autocomplete.Confidence", - current_match.confidence * 100); - - PredictAction predict_action = PREDICT_ACTION_NONE; - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kPrerenderFromOmnibox)) { - predict_action = RecommendPredictAction(current_match); - UMA_HISTOGRAM_ENUMERATION("Autocomplete.PredictAction", - predict_action, LAST_PREDICT_ACTION + 1); - } else if (!in_revert_ && controller_->GetTabContentsWrapper()) { - predict_action = PREDICT_ACTION_INSTANT; - } - string16 suggested_text; - bool might_support_instant = false; - switch (predict_action) { - case PREDICT_ACTION_INSTANT: - might_support_instant = - TryInstantFallbackToPrerender(current_match, &suggested_text); - break; - case PREDICT_ACTION_PRERENDER: - DoPrerender(current_match); - break; - case PREDICT_ACTION_PRECONNECT: - DoPreconnect(current_match); - break; - case PREDICT_ACTION_NONE: - break; - default: - NOTREACHED() << "Unexpected predict action: " << predict_action; - break; - } + if (!DoInstant(current_match, &suggested_text)) { + // Confer with the NetworkActionPredictor to determine what action, if any, + // we should take. + NetworkActionPredictor::Action action = NetworkActionPredictor::ACTION_NONE; + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kPrerenderFromOmnibox)) { + action = network_action_predictor_.RecommendAction(user_text_, + current_match); + UMA_HISTOGRAM_ENUMERATION("NetworkActionPredictor.Action", action, + NetworkActionPredictor::LAST_PREDICT_ACTION); + } + + switch (action) { + case NetworkActionPredictor::ACTION_PRERENDER: + DoPrerender(current_match); + break; + case NetworkActionPredictor::ACTION_PRECONNECT: + DoPreconnect(current_match); + break; + case NetworkActionPredictor::ACTION_NONE: + break; + default: + NOTREACHED() << "Unexpected predict action: " << action; + break; + } - if (!might_support_instant) { // Hide any suggestions we might be showing. view_->SetInstantSuggestion(string16(), false); @@ -1027,18 +974,17 @@ bool AutocompleteEditModel::ShouldAllowExactKeywordMatch( return keyword.length() && popup_->GetKeywordForText(keyword, &keyword); } -bool AutocompleteEditModel::TryInstantFallbackToPrerender( - const AutocompleteMatch& match, - string16* suggested_text) { +bool AutocompleteEditModel::DoInstant(const AutocompleteMatch& match, + string16* suggested_text) { DCHECK(suggested_text); + + if (in_revert_) + return false; + InstantController* instant = controller_->GetInstant(); - if (!instant) { - // Fall back to prerendering if necessary and possible. - if (user_input_in_progress() && popup_->IsOpen()) - DoPrerender(match); + if (!instant) return false; - } TabContentsWrapper* tab = controller_->GetTabContentsWrapper(); @@ -1073,8 +1019,10 @@ void AutocompleteEditModel::DoPrerender(const AutocompleteMatch& match) { void AutocompleteEditModel::DoPreconnect(const AutocompleteMatch& match) { if (!match.destination_url.SchemeIs(chrome::kExtensionScheme)) { // Warm up DNS Prefetch cache, or preconnect to a search service. + UMA_HISTOGRAM_ENUMERATION("Autocomplete.MatchType", match.type, + AutocompleteMatch::NUM_TYPES); chrome_browser_net::AnticipateOmniboxUrl(match.destination_url, - IsPreconnectable(match.type)); + NetworkActionPredictor::IsPreconnectable(match)); // We could prefetch the alternate nav URL, if any, but because there // can be many of these as a user types an initial series of characters, // the OS DNS cache could suffer eviction problems for minimal gain. diff --git a/chrome/browser/autocomplete/autocomplete_edit.h b/chrome/browser/autocomplete/autocomplete_edit.h index 40f3101..ff92b70 100644 --- a/chrome/browser/autocomplete/autocomplete_edit.h +++ b/chrome/browser/autocomplete/autocomplete_edit.h @@ -10,6 +10,7 @@ #include "base/string16.h" #include "chrome/browser/autocomplete/autocomplete_controller_delegate.h" #include "chrome/browser/autocomplete/autocomplete_match.h" +#include "chrome/browser/autocomplete/network_action_predictor.h" #include "chrome/common/instant_types.h" #include "content/common/page_transition_types.h" #include "googleurl/src/gurl.h" @@ -22,6 +23,7 @@ class AutocompleteEditModel; class AutocompletePopupModel; class AutocompleteResult; class InstantController; +class NetworkActionPredictor; class OmniboxView; class Profile; class SkBitmap; @@ -420,11 +422,9 @@ class AutocompleteEditModel : public AutocompleteControllerDelegate { const string16& new_user_text, size_t caret_position); - // Tries to start an instant preview for |match|. If instant is not supported, - // tries to start a prerender for it instead. Returns true if instant is + // Tries to start an instant preview for |match|. Returns true if instant is // supported. |suggested_text| must be non-NULL. - bool TryInstantFallbackToPrerender(const AutocompleteMatch& match, - string16* suggested_text); + bool DoInstant(const AutocompleteMatch& match, string16* suggested_text); // Starts a prerender for the given |match|. void DoPrerender(const AutocompleteMatch& match); @@ -555,6 +555,9 @@ class AutocompleteEditModel : public AutocompleteControllerDelegate { // Last value of InstantCompleteBehavior supplied to |SetSuggestedText|. InstantCompleteBehavior instant_complete_behavior_; + // Used to determine what network actions to take in different circumstances. + NetworkActionPredictor network_action_predictor_; + DISALLOW_COPY_AND_ASSIGN(AutocompleteEditModel); }; diff --git a/chrome/browser/autocomplete/autocomplete_match.cc b/chrome/browser/autocomplete/autocomplete_match.cc index 961994b..c879a9d 100644 --- a/chrome/browser/autocomplete/autocomplete_match.cc +++ b/chrome/browser/autocomplete/autocomplete_match.cc @@ -11,7 +11,6 @@ AutocompleteMatch::AutocompleteMatch() : provider(NULL), relevance(0), - confidence(0.0f), deletable(false), inline_autocomplete_offset(string16::npos), transition(PageTransition::GENERATED), @@ -24,12 +23,10 @@ AutocompleteMatch::AutocompleteMatch() AutocompleteMatch::AutocompleteMatch(AutocompleteProvider* provider, int relevance, - float confidence, bool deletable, Type type) : provider(provider), relevance(relevance), - confidence(confidence), deletable(deletable), inline_autocomplete_offset(string16::npos), transition(PageTransition::TYPED), diff --git a/chrome/browser/autocomplete/autocomplete_match.h b/chrome/browser/autocomplete/autocomplete_match.h index 6fbb780..fbf8355 100644 --- a/chrome/browser/autocomplete/autocomplete_match.h +++ b/chrome/browser/autocomplete/autocomplete_match.h @@ -85,7 +85,6 @@ struct AutocompleteMatch { AutocompleteMatch(); AutocompleteMatch(AutocompleteProvider* provider, int relevance, - float confidence, bool deletable, Type type); ~AutocompleteMatch(); @@ -140,10 +139,6 @@ struct AutocompleteMatch { // rather than being a fairly fixed value defined by the table above. int relevance; - // The confidence of the match. Calculated per provider and a measure in the - // range [0, 1]. - float confidence; - // True if the user should be able to delete this match. bool deletable; diff --git a/chrome/browser/autocomplete/autocomplete_unittest.cc b/chrome/browser/autocomplete/autocomplete_unittest.cc index 633c608..f56067d 100644 --- a/chrome/browser/autocomplete/autocomplete_unittest.cc +++ b/chrome/browser/autocomplete/autocomplete_unittest.cc @@ -86,7 +86,7 @@ void TestProvider::Run() { void TestProvider::AddResults(int start_at, int num) { for (int i = start_at; i < num; i++) { - AutocompleteMatch match(this, relevance_ - i, 0.0f, false, + AutocompleteMatch match(this, relevance_ - i, false, AutocompleteMatch::URL_WHAT_YOU_TYPED); match.fill_into_edit = prefix_ + UTF8ToUTF16(base::IntToString(i)); @@ -416,9 +416,9 @@ TEST(AutocompleteMatch, MoreRelevant) { { -5, -10, true }, }; - AutocompleteMatch m1(NULL, 0, 0.0f, false, + AutocompleteMatch m1(NULL, 0, false, AutocompleteMatch::URL_WHAT_YOU_TYPED); - AutocompleteMatch m2(NULL, 0, 0.0f, false, + AutocompleteMatch m2(NULL, 0, false, AutocompleteMatch::URL_WHAT_YOU_TYPED); for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { diff --git a/chrome/browser/autocomplete/builtin_provider.cc b/chrome/browser/autocomplete/builtin_provider.cc index 2559688..7fb5159 100644 --- a/chrome/browser/autocomplete/builtin_provider.cc +++ b/chrome/browser/autocomplete/builtin_provider.cc @@ -115,7 +115,7 @@ void BuiltinProvider::Start(const AutocompleteInput& input, void BuiltinProvider::AddMatch(const string16& match_string, const ACMatchClassifications& styles) { - AutocompleteMatch match(this, kRelevance, 0.0f, false, + AutocompleteMatch match(this, kRelevance, false, AutocompleteMatch::NAVSUGGEST); match.fill_into_edit = match_string; match.destination_url = GURL(match_string); diff --git a/chrome/browser/autocomplete/extension_app_provider.cc b/chrome/browser/autocomplete/extension_app_provider.cc index bbda5335..48ce96c 100644 --- a/chrome/browser/autocomplete/extension_app_provider.cc +++ b/chrome/browser/autocomplete/extension_app_provider.cc @@ -56,11 +56,7 @@ void ExtensionAppProvider::Start(const AutocompleteInput& input, // We have a match, might be a partial match. // TODO(finnur): Figure out what type to return here, might want to have // the extension icon/a generic icon show up in the Omnibox. - // TODO(dominich): Confidence would require us to create a match set and - // then iterate over to create the AutocompleteMatch objects. Currently - // confidence is used for instant/prerender/DNS preconnect and we may - // not want to do those for extension apps anyway. - AutocompleteMatch match(this, 0, 0.0f, false, + AutocompleteMatch match(this, 0, false, AutocompleteMatch::EXTENSION_APP); match.fill_into_edit = url; match.destination_url = GURL(url); diff --git a/chrome/browser/autocomplete/history_contents_provider.cc b/chrome/browser/autocomplete/history_contents_provider.cc index e6ab2a4..7061daf 100644 --- a/chrome/browser/autocomplete/history_contents_provider.cc +++ b/chrome/browser/autocomplete/history_contents_provider.cc @@ -29,11 +29,9 @@ const int kDaysToSearch = 30; HistoryContentsProvider::MatchReference::MatchReference( const history::URLResult* result, - int relevance, - float confidence) + int relevance) : result(result), - relevance(relevance), - confidence(confidence) { + relevance(relevance) { } // static @@ -182,8 +180,7 @@ void HistoryContentsProvider::ConvertResults() { for (std::vector<history::URLResult*>::const_reverse_iterator i = results_.rbegin(); i != results_.rend(); ++i) { history::URLResult* result = *i; - MatchReference ref(result, CalculateRelevance(*result), - CalculateConfidence(*result, results_)); + MatchReference ref(result, CalculateRelevance(*result)); result_refs.push_back(ref); } @@ -194,8 +191,6 @@ void HistoryContentsProvider::ConvertResults() { matches_.clear(); for (size_t i = 0; i < max_for_provider; i++) { AutocompleteMatch match(ResultToMatch(result_refs[i])); - UMA_HISTOGRAM_COUNTS_100("Autocomplete.Confidence_HistoryContents", - match.confidence * 100); matches_.push_back(match); } } @@ -208,8 +203,8 @@ bool HistoryContentsProvider::MatchInTitle(const history::URLResult& result) { AutocompleteMatch HistoryContentsProvider::ResultToMatch( const MatchReference& match_reference) { const history::URLResult& result = *match_reference.result; - AutocompleteMatch match(this, match_reference.relevance, - match_reference.confidence, true, MatchInTitle(result) ? + AutocompleteMatch match(this, match_reference.relevance, true, + MatchInTitle(result) ? AutocompleteMatch::HISTORY_TITLE : AutocompleteMatch::HISTORY_BODY); match.contents = StringForURLDisplay(result.url(), true, trim_http_); match.fill_into_edit = @@ -262,46 +257,6 @@ int HistoryContentsProvider::CalculateRelevance( (1000 + star_title_count_++) : (550 + star_contents_count_++); } -float HistoryContentsProvider::CalculateConfidence( - const history::URLResult& result, - const history::QueryResults& results) const { - // Calculate a score of [0, 0.9] based on typed count. - // Using typed count in place of visit count as: - // - It's a better indicator of what the user wants to open given that they - // are typing in the address bar (users tend to open certain URLs by typing - // and others by e.g. bookmarks, so visit_count is a good indicator of - // overall interest but a bad one for specifically omnibox interest). - // - Since the DB query is sorted by typed_count, the results may be - // effectively a random selection as far as visit_counts are concerned - // (meaning many high-visit_count-URLs may be present in one query and - // absent in a similar one), leading to wild swings in confidence for the - // same result across distinct queries. - float numerator = result.typed_count(); - float denominator = 0.0f; - for (std::vector<history::URLResult*>::const_iterator it = results.begin(); - it != results.end(); ++it) { - denominator += (*it)->typed_count(); - } - // It should only be equal to 0 if the result is not in the results vector. - if (denominator < 1) { - numerator = result.visit_count(); - for (std::vector<history::URLResult*>::const_iterator it = results.begin(); - it != results.end(); ++it) { - denominator += (*it)->visit_count(); - } - } - - float score = 0.9f * (denominator > 0.0f ? numerator / denominator : 0); - - // Add 0.1 if the URL is bookmarked to get a final range of [0, 1]. - if (profile_->GetBookmarkModel() && - profile_->GetBookmarkModel()->IsBookmarked(result.url())) { - score += 0.1f; - } - - return score; -} - void HistoryContentsProvider::QueryBookmarks(const AutocompleteInput& input) { BookmarkModel* bookmark_model = profile_->GetBookmarkModel(); if (!bookmark_model) diff --git a/chrome/browser/autocomplete/history_contents_provider.h b/chrome/browser/autocomplete/history_contents_provider.h index f4fd334..982e83b 100644 --- a/chrome/browser/autocomplete/history_contents_provider.h +++ b/chrome/browser/autocomplete/history_contents_provider.h @@ -40,15 +40,13 @@ class HistoryContentsProvider : public HistoryProvider { // without modifying the larger and slower results structure. struct MatchReference { MatchReference(const history::URLResult* result, - int relevance, - float confidence); + int relevance); static bool CompareRelevance(const MatchReference& lhs, const MatchReference& rhs); const history::URLResult* result; int relevance; // Score of relevance computed by CalculateRelevance. - float confidence; // Confidence computed by CalculateConfidence. }; virtual ~HistoryContentsProvider(); @@ -72,12 +70,6 @@ class HistoryContentsProvider : public HistoryProvider { // chart in autocomplete.h for the list of values this returns. int CalculateRelevance(const history::URLResult& result); - // Calculates and returns the confidence for a particular result. This is - // calculated by comparing the result's |visit_count| to that of all the - // results. - float CalculateConfidence(const history::URLResult& result, - const history::QueryResults& results) const; - // Queries the bookmarks for any bookmarks whose title matches input. All // matches are added directly to results_. void QueryBookmarks(const AutocompleteInput& input); diff --git a/chrome/browser/autocomplete/history_quick_provider.cc b/chrome/browser/autocomplete/history_quick_provider.cc index 8a96c52..fbdc559 100644 --- a/chrome/browser/autocomplete/history_quick_provider.cc +++ b/chrome/browser/autocomplete/history_quick_provider.cc @@ -119,8 +119,6 @@ void HistoryQuickProvider::DoAutocomplete() { history_match, matches, PreventInlineAutocomplete(autocomplete_input_), &max_match_score); - UMA_HISTOGRAM_COUNTS_100("Autocomplete.Confidence_HistoryQuick", - ac_match.confidence * 100); matches_.push_back(ac_match); } } @@ -134,11 +132,9 @@ AutocompleteMatch HistoryQuickProvider::QuickMatchToACMatch( DCHECK(max_match_score); const history::URLRow& info = history_match.url_info; int score = CalculateRelevance(history_match, max_match_score); - float confidence = CalculateConfidence(history_match, history_matches); - AutocompleteMatch match(this, score, confidence, !!info.visit_count(), - history_match.url_matches.empty() ? - AutocompleteMatch::HISTORY_URL : - AutocompleteMatch::HISTORY_TITLE); + AutocompleteMatch match(this, score, !!info.visit_count(), + history_match.url_matches.empty() ? + AutocompleteMatch::HISTORY_URL : AutocompleteMatch::HISTORY_TITLE); match.destination_url = info.url(); DCHECK(match.destination_url.is_valid()); @@ -206,20 +202,6 @@ int HistoryQuickProvider::CalculateRelevance( } // static -float HistoryQuickProvider::CalculateConfidence( - const ScoredHistoryMatch& match, - const ScoredHistoryMatches& matches) { - float denominator = 0.0f; - for (ScoredHistoryMatches::const_iterator it = matches.begin(); - it != matches.end(); ++it) { - denominator += it->raw_score; - } - DCHECK(denominator > 0); - - return static_cast<float>(match.raw_score) / denominator; -} - -// static ACMatchClassifications HistoryQuickProvider::SpansFromTermMatch( const history::TermMatches& matches, size_t text_length, diff --git a/chrome/browser/autocomplete/history_quick_provider.h b/chrome/browser/autocomplete/history_quick_provider.h index e6bb353..8264669 100644 --- a/chrome/browser/autocomplete/history_quick_provider.h +++ b/chrome/browser/autocomplete/history_quick_provider.h @@ -70,12 +70,6 @@ class HistoryQuickProvider : public HistoryProvider { const history::ScoredHistoryMatch& history_match, int* max_match_score); - // Determines the confidence of |match| by comparing the |raw_score| to the - // sum of the scores of |matches|. Returns a float in the range [0, 1]. - static float CalculateConfidence( - const history::ScoredHistoryMatch& match, - const history::ScoredHistoryMatches& matches); - // Returns the index that should be used for history lookups. history::InMemoryURLIndex* GetIndex(); diff --git a/chrome/browser/autocomplete/history_url_provider.cc b/chrome/browser/autocomplete/history_url_provider.cc index c7cf7f7..3340ad4 100644 --- a/chrome/browser/autocomplete/history_url_provider.cc +++ b/chrome/browser/autocomplete/history_url_provider.cc @@ -201,48 +201,6 @@ bool CompareHistoryMatch(const history::HistoryMatch& a, return a.url_info.last_visit() > b.url_info.last_visit(); } -// Determines the confidence for a |match| when compared to all the |matches|. -// Returns a number in the range [0, 1]. -float CalculateConfidence(const history::HistoryMatch& match, - const history::HistoryMatches& matches) { - // Calculate a score based on typed count. - const float typed_numerator = match.url_info.typed_count(); - float typed_denominator = 0.0f; - for (history::HistoryMatches::const_iterator it = matches.begin(); - it != matches.end(); ++it) { - typed_denominator += it->url_info.typed_count(); - } - const float typed_score = (typed_denominator > 0.0f) ? - (typed_numerator / typed_denominator) : 0.0f; - - // Calculate a score based on visit count - const float visit_numerator = match.url_info.visit_count(); - float visit_denominator = 0.0f; - for (history::HistoryMatches::const_iterator it = matches.begin(); - it != matches.end(); ++it) { - visit_denominator += it->url_info.visit_count(); - } - const float visit_score = (visit_denominator > 0.0f) ? - (visit_numerator / visit_denominator) : 0.0f; - - // Calculate a score based on innermost matching. - const float innermost_score = (match.innermost_match ? 1.0f : 0.0f); - - // TODO(dominich): Add a boost for bookmarked pages? - // Prefer typed count to visit count as: - // - It's a better indicator of what the user wants to open given that they - // are typing in the address bar (users tend to open certain URLs by typing - // and others by e.g. bookmarks, so visit_count is a good indicator of - // overall interest but a bad one for specifically omnibox interest). - // - Since the DB query is sorted by typed_count, the results may be - // effectively a random selection as far as visit_counts are concerned - // (meaning many high-visit_count-URLs may be present in one query and - // absent in a similar one), leading to wild swings in confidence for the - // same result across distinct queries. - // Add a boost for innermost matches (matches after scheme or 'www.'). - return (0.5f * typed_score) + (0.3f * visit_score) + (0.2f * innermost_score); -} - } // namespace HistoryURLProviderParams::HistoryURLProviderParams( @@ -415,8 +373,6 @@ void HistoryURLProvider::DoAutocomplete(history::HistoryBackend* backend, AutocompleteMatch ac_match = HistoryMatchToACMatch(params, match, history_matches, NORMAL, history_matches.size() - 1 - i); - UMA_HISTOGRAM_COUNTS_100("Autocomplete.Confidence_HistoryUrl", - ac_match.confidence * 100); params->matches.push_back(ac_match); } } @@ -597,12 +553,9 @@ const history::Prefix* HistoryURLProvider::BestPrefix( AutocompleteMatch HistoryURLProvider::SuggestExactInput( const AutocompleteInput& input, bool trim_http) { - // TODO(dominich): Find a confidence measure for this. AutocompleteMatch match(this, - CalculateRelevance(input.type(), WHAT_YOU_TYPED, 0), 0.0f, false, + CalculateRelevance(input.type(), WHAT_YOU_TYPED, 0), false, AutocompleteMatch::URL_WHAT_YOU_TYPED); - UMA_HISTOGRAM_COUNTS_100("Autocomplete.Confidence_HistoryUrl", - match.confidence * 100); const GURL& url = input.canonicalized_url(); if (url.is_valid()) { @@ -887,7 +840,6 @@ AutocompleteMatch HistoryURLProvider::HistoryMatchToACMatch( const history::URLRow& info = history_match.url_info; AutocompleteMatch match(this, CalculateRelevance(params->input.type(), match_type, match_number), - CalculateConfidence(history_match, history_matches), !!info.visit_count(), AutocompleteMatch::HISTORY_URL); match.destination_url = info.url(); DCHECK(match.destination_url.is_valid()); diff --git a/chrome/browser/autocomplete/keyword_provider.cc b/chrome/browser/autocomplete/keyword_provider.cc index 399c2a3..957ad97 100644 --- a/chrome/browser/autocomplete/keyword_provider.cc +++ b/chrome/browser/autocomplete/keyword_provider.cc @@ -415,8 +415,7 @@ AutocompleteMatch KeywordProvider::CreateAutocompleteMatch( supports_replacement, input.prefer_keyword(), input.allow_exact_keyword_match()); } - // TODO(dominich): Confidence. Not sure how to calculate it for this provider. - AutocompleteMatch result(this, relevance, 0.0f, false, + AutocompleteMatch result(this, relevance, false, supports_replacement ? AutocompleteMatch::SEARCH_OTHER_ENGINE : AutocompleteMatch::HISTORY_KEYWORD); result.fill_into_edit.assign(keyword); diff --git a/chrome/browser/autocomplete/network_action_predictor.cc b/chrome/browser/autocomplete/network_action_predictor.cc new file mode 100644 index 0000000..71a3cd2 --- /dev/null +++ b/chrome/browser/autocomplete/network_action_predictor.cc @@ -0,0 +1,100 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/autocomplete/network_action_predictor.h" + +#include <math.h> + +#include "base/i18n/case_conversion.h" +#include "base/metrics/histogram.h" +#include "base/string_util.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/autocomplete/autocomplete_match.h" +#include "chrome/browser/history/history.h" +#include "chrome/browser/history/in_memory_database.h" +#include "chrome/browser/profiles/profile.h" + +namespace { + + const float kConfidenceCutoff[NetworkActionPredictor::LAST_PREDICT_ACTION] = { + 0.8f, + 0.5f + }; + +} + +NetworkActionPredictor::NetworkActionPredictor(Profile* profile) + : profile_(profile) { +} + +NetworkActionPredictor::~NetworkActionPredictor() { +} + +// Given a match, return a recommended action. +NetworkActionPredictor::Action + NetworkActionPredictor::RecommendAction( + const string16& user_text, const AutocompleteMatch& match) const { + HistoryService* history_service = + profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); + if (!history_service) + return ACTION_NONE; + + history::URLDatabase* url_db = history_service->InMemoryDatabase(); + if (!url_db) + return ACTION_NONE; + + history::URLRow url_row; + history::URLID url_id = url_db->GetRowForURL(match.destination_url, &url_row); + + if (url_id == 0) + return ACTION_NONE; + + const double base_score = 1.0; + + // This constant is ln(1/0.8) so we end up decaying to 80% of the base score + // for each week that passes. + const double kLnDecayPercent = 0.2231435513142097; + base::TimeDelta time_passed = base::Time::Now() - url_row.last_visit(); + + // Clamp to 0. + const double decay_exponent = std::max(0.0, + kLnDecayPercent * static_cast<double>(time_passed.InMicroseconds()) / + base::Time::kMicrosecondsPerWeek); + + const double kMaxDecaySpeedDivisor = 5.0; + const double kNumUsesPerDecaySpeedDivisorIncrement = 1.0; + const double decay_divisor = std::min(kMaxDecaySpeedDivisor, + (url_row.typed_count() + kNumUsesPerDecaySpeedDivisorIncrement - 1) / + kNumUsesPerDecaySpeedDivisorIncrement); + + const double confidence = base_score / exp(decay_exponent / decay_divisor); + + CHECK(confidence >= 0.0 && confidence <= 1.0); + + UMA_HISTOGRAM_COUNTS_100("NetworkActionPredictor.Confidence", + confidence * 100); + + for (int i = 0; i < LAST_PREDICT_ACTION; ++i) + if (confidence >= kConfidenceCutoff[i]) + return static_cast<Action>(i); + return ACTION_NONE; +} + +// Return true if the suggestion type warrants a TCP/IP preconnection. +// i.e., it is now quite likely that the user will select the related domain. +// static +bool NetworkActionPredictor::IsPreconnectable(const AutocompleteMatch& match) { + switch (match.type) { + // Matches using the user's default search engine. + case AutocompleteMatch::SEARCH_WHAT_YOU_TYPED: + case AutocompleteMatch::SEARCH_HISTORY: + case AutocompleteMatch::SEARCH_SUGGEST: + // A match that uses a non-default search engine (e.g. for tab-to-search). + case AutocompleteMatch::SEARCH_OTHER_ENGINE: + return true; + + default: + return false; + } +} diff --git a/chrome/browser/autocomplete/network_action_predictor.h b/chrome/browser/autocomplete/network_action_predictor.h new file mode 100644 index 0000000..5be8597 --- /dev/null +++ b/chrome/browser/autocomplete/network_action_predictor.h @@ -0,0 +1,45 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_AUTOCOMPLETE_NETWORK_ACTION_PREDICTOR_H_ +#define CHROME_BROWSER_AUTOCOMPLETE_NETWORK_ACTION_PREDICTOR_H_ +#pragma once + +#include "base/string16.h" + +struct AutocompleteMatch; +class Profile; + +// This class is responsible for determining the correct predictive network +// action to take given for a given AutocompleteMatch and entered text. +class NetworkActionPredictor { + public: + enum Action { + ACTION_PRERENDER = 0, + ACTION_PRECONNECT, + ACTION_NONE, + LAST_PREDICT_ACTION = ACTION_NONE + }; + + explicit NetworkActionPredictor(Profile* profile); + virtual ~NetworkActionPredictor(); + + // Return the recommended action given |user_text|, the text the user has + // entered in the Omnibox, and |match|, the suggestion from Autocomplete. + // This method uses information from the ShortcutsBackend including how much + // of the matching entry the user typed, and how long it's been since the user + // visited the matching URL, to calculate a score between 0 and 1. This score + // is then mapped to an Action. + Action RecommendAction(const string16& user_text, + const AutocompleteMatch& match) const; + + // Return true if the suggestion type warrants a TCP/IP preconnection. + // i.e., it is now quite likely that the user will select the related domain. + static bool IsPreconnectable(const AutocompleteMatch& match); + + private: + Profile* profile_; +}; + +#endif // CHROME_BROWSER_AUTOCOMPLETE_NETWORK_ACTION_PREDICTOR_H_ diff --git a/chrome/browser/autocomplete/network_action_predictor_unittest.cc b/chrome/browser/autocomplete/network_action_predictor_unittest.cc new file mode 100644 index 0000000..db95a65 --- /dev/null +++ b/chrome/browser/autocomplete/network_action_predictor_unittest.cc @@ -0,0 +1,102 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/autocomplete/network_action_predictor.h" + +#include "base/message_loop.h" +#include "base/time.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/autocomplete/autocomplete_match.h" +#include "chrome/browser/history/history.h" +#include "chrome/browser/history/url_database.h" +#include "chrome/test/base/testing_profile.h" +#include "content/browser/browser_thread.h" +#include "testing/gtest/include/gtest/gtest.h" + +typedef testing::Test NetworkActionPredictorTest; + +TEST_F(NetworkActionPredictorTest, RecommendAction) { + MessageLoop loop(MessageLoop::TYPE_DEFAULT); + BrowserThread ui_thread(BrowserThread::UI, &loop); + BrowserThread file_thread(BrowserThread::FILE, &loop); + + TestingProfile profile; + profile.CreateHistoryService(true, false); + profile.BlockUntilHistoryProcessesPendingRequests(); + + NetworkActionPredictor predictor(&profile); + + HistoryService* history = profile.GetHistoryService(Profile::EXPLICIT_ACCESS); + CHECK(history); + history::URLDatabase* url_db = history->InMemoryDatabase(); + CHECK(url_db); + + struct TestUrlInfo { + GURL url; + string16 title; + int typed_count; + int days_from_now; + string16 user_text; + NetworkActionPredictor::Action expected_action; + } test_url_db[] = { + { GURL("http://www.testsite.com/a.html"), + ASCIIToUTF16("Test - site - just a test"), 1, 1, + ASCIIToUTF16("just"), + NetworkActionPredictor::ACTION_PRERENDER }, + { GURL("http://www.testsite.com/b.html"), + ASCIIToUTF16("Test - site - just a test"), 0, 1, + ASCIIToUTF16("just"), + NetworkActionPredictor::ACTION_NONE }, + { GURL("http://www.testsite.com/c.html"), + ASCIIToUTF16("Test - site - just a test"), 1, 5, + ASCIIToUTF16("just"), + NetworkActionPredictor::ACTION_PRERENDER }, + { GURL("http://www.testsite.com/d.html"), + ASCIIToUTF16("Test - site - just a test"), 2, 5, + ASCIIToUTF16("just"), + NetworkActionPredictor::ACTION_PRERENDER }, + { GURL("http://www.testsite.com/e.html"), + ASCIIToUTF16("Test - site - just a test"), 1, 8, + ASCIIToUTF16("just"), + NetworkActionPredictor::ACTION_PRECONNECT }, + { GURL("http://www.testsite.com/f.html"), + ASCIIToUTF16("Test - site - just a test"), 4, 8, + ASCIIToUTF16("just"), + NetworkActionPredictor::ACTION_PRERENDER }, + { GURL("http://www.testsite.com/g.html"), + ASCIIToUTF16("Test - site - just a test"), 1, 12, + ASCIIToUTF16("just a"), + NetworkActionPredictor::ACTION_PRECONNECT }, + { GURL("http://www.testsite.com/h.html"), + ASCIIToUTF16("Test - site - just a test"), 1, 21, + ASCIIToUTF16("just a test"), + NetworkActionPredictor::ACTION_PRECONNECT }, + { GURL("http://www.testsite.com/i.html"), + ASCIIToUTF16("Test - site - just a test"), 1, 28, + ASCIIToUTF16("just a test"), + NetworkActionPredictor::ACTION_NONE } + }; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_url_db); ++i) { + const base::Time visit_time = + base::Time::Now() - base::TimeDelta::FromDays( + test_url_db[i].days_from_now); + + history::URLRow row(test_url_db[i].url); + row.set_title(test_url_db[i].title); + row.set_typed_count(test_url_db[i].typed_count); + row.set_last_visit(visit_time); + + CHECK(url_db->AddURL(row)); + } + + AutocompleteMatch match; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_url_db); ++i) { + match.destination_url = GURL(test_url_db[i].url); + EXPECT_EQ(test_url_db[i].expected_action, + predictor.RecommendAction(test_url_db[i].user_text, match)) + << "Unexpected action for " << match.destination_url; + } +} diff --git a/chrome/browser/autocomplete/search_provider.cc b/chrome/browser/autocomplete/search_provider.cc index 1dae40a..11a335b 100644 --- a/chrome/browser/autocomplete/search_provider.cc +++ b/chrome/browser/autocomplete/search_provider.cc @@ -815,10 +815,7 @@ void SearchProvider::AddMatchToMap(const string16& query_string, bool is_keyword, bool prevent_inline_autocomplete, MatchMap* map) { - // TODO(dominich): Confidence. In this case, the confidence must depend on the - // source. Scored terms can be calculated based on score, but other sources - // need more care. Eg, suggest. - AutocompleteMatch match(this, relevance, 0.0f, false, type); + AutocompleteMatch match(this, relevance, false, type); std::vector<size_t> content_param_offsets; const TemplateURL& provider = is_keyword ? providers_.keyword_provider() : providers_.default_provider(); @@ -916,8 +913,7 @@ AutocompleteMatch SearchProvider::NavigationToMatch( bool is_keyword) { const string16& input_text = is_keyword ? keyword_input_text_ : input_.text(); - // TODO(dominich): Confidence calculation. - AutocompleteMatch match(this, relevance, 0.0f, false, + AutocompleteMatch match(this, relevance, false, AutocompleteMatch::NAVSUGGEST); match.destination_url = navigation.url; match.contents = diff --git a/chrome/browser/autocomplete/shortcuts_provider.cc b/chrome/browser/autocomplete/shortcuts_provider.cc index 6991c678..1b29dac 100644 --- a/chrome/browser/autocomplete/shortcuts_provider.cc +++ b/chrome/browser/autocomplete/shortcuts_provider.cc @@ -117,7 +117,7 @@ void ShortcutsProvider::OnShortcutsLoaded() { LoadShortcuts(); } -void ShortcutsProvider::OnShortcutAddedOrUpdated(Shortcut shortcut) { +void ShortcutsProvider::OnShortcutAddedOrUpdated(const Shortcut& shortcut) { shortcuts_provider::GuidToShortcutsIteratorMap::iterator it = guid_map_.find(shortcut.id); if (it != guid_map_.end()) { @@ -128,7 +128,7 @@ void ShortcutsProvider::OnShortcutAddedOrUpdated(Shortcut shortcut) { } void ShortcutsProvider::OnShortcutsRemoved( - std::vector<std::string> shortcuts_ids) { + const std::vector<std::string>& shortcuts_ids) { for (size_t i = 0; i < shortcuts_ids.size(); ++i) { shortcuts_provider::GuidToShortcutsIteratorMap::iterator it = guid_map_.find(shortcuts_ids[i]); @@ -183,9 +183,7 @@ AutocompleteMatch ShortcutsProvider::ShortcutToACMatch( const AutocompleteInput& input, const string16& term_string, ShortcutMap::iterator it) { - // TODO(dominich): Use the same score calculation for confidence and - // relevance. - AutocompleteMatch match(this, CalculateScore(term_string, it->second), 0.0f, + AutocompleteMatch match(this, CalculateScore(term_string, it->second), true, AutocompleteMatch::HISTORY_TITLE); match.destination_url = it->second.url; DCHECK(match.destination_url.is_valid()); diff --git a/chrome/browser/autocomplete/shortcuts_provider.h b/chrome/browser/autocomplete/shortcuts_provider.h index 02522d4..38161d4 100644 --- a/chrome/browser/autocomplete/shortcuts_provider.h +++ b/chrome/browser/autocomplete/shortcuts_provider.h @@ -50,9 +50,11 @@ class ShortcutsProvider static const int kMaxScore; // ShortcutsBackendObserver: - virtual void OnShortcutsLoaded(); - virtual void OnShortcutAddedOrUpdated(shortcuts_provider::Shortcut shortcut); - virtual void OnShortcutsRemoved(std::vector<std::string> shortcut_ids); + virtual void OnShortcutsLoaded() OVERRIDE; + virtual void OnShortcutAddedOrUpdated( + const shortcuts_provider::Shortcut& shortcut) OVERRIDE; + virtual void OnShortcutsRemoved( + const std::vector<std::string>& shortcut_ids) OVERRIDE; void DeleteMatchesWithURLs(const std::set<GURL>& urls); void DeleteShortcutsWithURLs(const std::set<GURL>& urls); diff --git a/chrome/browser/autocomplete/shortcuts_provider_unittest.cc b/chrome/browser/autocomplete/shortcuts_provider_unittest.cc index be748cc..534c53d 100644 --- a/chrome/browser/autocomplete/shortcuts_provider_unittest.cc +++ b/chrome/browser/autocomplete/shortcuts_provider_unittest.cc @@ -21,7 +21,6 @@ #include "chrome/browser/history/url_database.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/common/pref_names.h" -#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "content/browser/browser_thread.h" #include "testing/gtest/include/gtest/gtest.h" @@ -29,6 +28,8 @@ using base::Time; using base::TimeDelta; +namespace { + struct TestShortcutInfo { std::string url; std::string title; // The text that orginally was searched for. @@ -94,6 +95,8 @@ struct TestShortcutInfo { "Test - site", "0,0", 1, 4}, }; +} // end namespace + class ShortcutsProviderTest : public testing::Test, public ACProviderListener { public: @@ -569,7 +572,7 @@ TEST_F(ShortcutsProviderTest, DeleteMatch) { EXPECT_FALSE(provider_->shortcuts_map_.end() == provider_->shortcuts_map_.find(ASCIIToUTF16("erase"))); - AutocompleteMatch match(provider_, 1200, 0.0f, true, + AutocompleteMatch match(provider_, 1200, true, AutocompleteMatch::HISTORY_TITLE); match.destination_url = GURL(shortcuts_to_test_delete[0].url); diff --git a/chrome/browser/history/shortcuts_backend.h b/chrome/browser/history/shortcuts_backend.h index f7b625b..abaccd3 100644 --- a/chrome/browser/history/shortcuts_backend.h +++ b/chrome/browser/history/shortcuts_backend.h @@ -47,10 +47,10 @@ class ShortcutsBackend : public base::RefCountedThreadSafe<ShortcutsBackend>, // This callback is called when addition or change was processed by the // database. virtual void OnShortcutAddedOrUpdated( - shortcuts_provider::Shortcut shortcut) = 0; + const shortcuts_provider::Shortcut& shortcut) = 0; // Called when shortcuts are removed from the database. virtual void OnShortcutsRemoved( - std::vector<std::string> shortcut_ids) = 0; + const std::vector<std::string>& shortcut_ids) = 0; protected: virtual ~ShortcutsBackendObserver() {} }; diff --git a/chrome/browser/history/shortcuts_backend_unittest.cc b/chrome/browser/history/shortcuts_backend_unittest.cc index 97be955..0bad07c 100644 --- a/chrome/browser/history/shortcuts_backend_unittest.cc +++ b/chrome/browser/history/shortcuts_backend_unittest.cc @@ -36,9 +36,9 @@ class ShortcutsBackendTest : public testing::Test, void TearDown(); virtual void OnShortcutsLoaded() OVERRIDE; - virtual void OnShortcutAddedOrUpdated(Shortcut shortcut) OVERRIDE; + virtual void OnShortcutAddedOrUpdated(const Shortcut& shortcut) OVERRIDE; virtual void OnShortcutsRemoved( - std::vector<std::string> shortcut_ids) OVERRIDE; + const std::vector<std::string>& shortcut_ids) OVERRIDE; void InitBackend(); @@ -70,13 +70,13 @@ void ShortcutsBackendTest::OnShortcutsLoaded() { MessageLoop::current()->Quit(); } -void ShortcutsBackendTest::OnShortcutAddedOrUpdated(Shortcut shortcut) { +void ShortcutsBackendTest::OnShortcutAddedOrUpdated(const Shortcut& shortcut) { notified_shortcut_ = shortcut; MessageLoop::current()->Quit(); } void ShortcutsBackendTest::OnShortcutsRemoved( - std::vector<std::string> shortcut_ids) { + const std::vector<std::string>& shortcut_ids) { notified_shortcut_ids_ = shortcut_ids; MessageLoop::current()->Quit(); } diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac_unittest.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac_unittest.mm index 17b60b0..178acec 100644 --- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac_unittest.mm +++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac_unittest.mm @@ -88,8 +88,7 @@ class OmniboxPopupViewMacTest : public PlatformTest { // needs. Fake one for us to use. static AutocompleteMatch MakeMatch(const string16 &contents, const string16 &description) { - AutocompleteMatch m(NULL, 1, 0.0f, true, - AutocompleteMatch::URL_WHAT_YOU_TYPED); + AutocompleteMatch m(NULL, 1, true, AutocompleteMatch::URL_WHAT_YOU_TYPED); m.contents = contents; m.description = description; return m; |