diff options
author | dominich@chromium.org <dominich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-21 21:53:29 +0000 |
---|---|---|
committer | dominich@chromium.org <dominich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-21 21:53:29 +0000 |
commit | 317932e490d531cfa144c05e3d4862555fa0d4e1 (patch) | |
tree | 7968022b00317fb9da8db6051da78c459ade41ce /chrome/browser/autocomplete | |
parent | 068f74ffe6d13a6d8e375564d74b39d3eb53c2a6 (diff) | |
download | chromium_src-317932e490d531cfa144c05e3d4862555fa0d4e1.zip chromium_src-317932e490d531cfa144c05e3d4862555fa0d4e1.tar.gz chromium_src-317932e490d531cfa144c05e3d4862555fa0d4e1.tar.bz2 |
Adding a fourth omnibox prerender experiment.
This adds or updates entries in the database for the entire chain of text the user typed. For example, if the user types 'goog' and navigates to google.com, this will add or update database entries for 'go' -> google.com, 'goo' -> google.com and 'goog' -> google.com.
BUG=
TEST=
Review URL: http://codereview.chromium.org/8600004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111005 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/autocomplete')
-rw-r--r-- | chrome/browser/autocomplete/autocomplete_edit.cc | 32 | ||||
-rw-r--r-- | chrome/browser/autocomplete/network_action_predictor.cc | 143 | ||||
-rw-r--r-- | chrome/browser/autocomplete/network_action_predictor.h | 30 |
3 files changed, 160 insertions, 45 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_edit.cc b/chrome/browser/autocomplete/autocomplete_edit.cc index 096d2ad..6c971b8 100644 --- a/chrome/browser/autocomplete/autocomplete_edit.cc +++ b/chrome/browser/autocomplete/autocomplete_edit.cc @@ -213,23 +213,29 @@ bool AutocompleteEditModel::AcceptCurrentInstantPreview() { void AutocompleteEditModel::OnChanged() { const AutocompleteMatch current_match = CurrentMatch(); - string16 suggested_text; - - // Confer with the NetworkActionPredictor to determine what action, if any, - // we should take. Get the recommended action here even if we don't need it - // so we can get stats for anyone who is opted in to UMA, but only get it if - // the user has actually typed something to avoid constructing it before it's - // needed. Note: This event is triggered as part of startup when the initial - // tab transitions to the start page. + NetworkActionPredictor::Action recommended_action = + NetworkActionPredictor::ACTION_NONE; NetworkActionPredictor* network_action_predictor = user_input_in_progress() ? profile_->GetNetworkActionPredictor() : NULL; - NetworkActionPredictor::Action recommended_action = network_action_predictor ? - network_action_predictor->RecommendAction(user_text_, current_match) : - NetworkActionPredictor::ACTION_NONE; + if (network_action_predictor) { + network_action_predictor->RegisterTransitionalMatches(user_text_, + result()); + // Confer with the NetworkActionPredictor to determine what action, if any, + // we should take. Get the recommended action here even if we don't need it + // so we can get stats for anyone who is opted in to UMA, but only get it if + // the user has actually typed something to avoid constructing it before + // it's needed. Note: This event is triggered as part of startup when the + // initial tab transitions to the start page. + recommended_action = + network_action_predictor->RecommendAction(user_text_, current_match); + } + UMA_HISTOGRAM_ENUMERATION("NetworkActionPredictor.Action_" + prerender::GetOmniboxHistogramSuffix(), recommended_action, NetworkActionPredictor::LAST_PREDICT_ACTION); + string16 suggested_text; + if (DoInstant(current_match, &suggested_text)) { SetSuggestedText(suggested_text, instant_complete_behavior_); } else { @@ -394,6 +400,10 @@ void AutocompleteEditModel::Revert() { has_temporary_text_ = false; view_->SetWindowTextAndCaretPos(permanent_text_, has_focus_ ? permanent_text_.length() : 0); + NetworkActionPredictor* network_action_predictor = + profile_->GetNetworkActionPredictor(); + if (network_action_predictor) + network_action_predictor->ClearTransitionalMatches(); } void AutocompleteEditModel::StartAutocomplete( diff --git a/chrome/browser/autocomplete/network_action_predictor.cc b/chrome/browser/autocomplete/network_action_predictor.cc index 31066d2..31c922c 100644 --- a/chrome/browser/autocomplete/network_action_predictor.cc +++ b/chrome/browser/autocomplete/network_action_predictor.cc @@ -130,6 +130,42 @@ NetworkActionPredictor::~NetworkActionPredictor() { db_->OnPredictorDestroyed(); } +void NetworkActionPredictor::RegisterTransitionalMatches( + const string16& user_text, + const AutocompleteResult& result) { + if (prerender::GetOmniboxHeuristicToUse() != + prerender::OMNIBOX_HEURISTIC_EXACT_FULL) { + return; + } + if (user_text.length() < kMinimumUserTextLength) + return; + const string16 lower_user_text(base::i18n::ToLower(user_text)); + + // Merge this in to an existing match if we already saw |user_text| + std::vector<TransitionalMatch>::iterator match_it = + std::find(transitional_matches_.begin(), transitional_matches_.end(), + lower_user_text); + + if (match_it == transitional_matches_.end()) { + TransitionalMatch transitional_match; + transitional_match.user_text = lower_user_text; + match_it = transitional_matches_.insert(transitional_matches_.end(), + transitional_match); + } + + for (AutocompleteResult::const_iterator it = result.begin(); + it != result.end(); ++it) { + if (std::find(match_it->urls.begin(), match_it->urls.end(), + it->destination_url) == match_it->urls.end()) { + match_it->urls.push_back(it->destination_url); + } + } +} + +void NetworkActionPredictor::ClearTransitionalMatches() { + transitional_matches_.clear(); +} + // Given a match, return a recommended action. NetworkActionPredictor::Action NetworkActionPredictor::RecommendAction( const string16& user_text, @@ -150,6 +186,7 @@ NetworkActionPredictor::Action NetworkActionPredictor::RecommendAction( break; } case prerender::OMNIBOX_HEURISTIC_EXACT: + case prerender::OMNIBOX_HEURISTIC_EXACT_FULL: confidence = ExactAlgorithm(user_text, match); break; default: @@ -225,40 +262,10 @@ void NetworkActionPredictor::Observe( // and those are the events we're most interested in. case chrome::NOTIFICATION_OMNIBOX_OPENED_URL: { DCHECK(initialized_); - AutocompleteLog* log = content::Details<AutocompleteLog>(details).ptr(); - if (log->text.length() < kMinimumUserTextLength) - break; - - const string16 lower_user_text(base::i18n::ToLower(log->text)); - - BeginTransaction(); - for (size_t i = 0; i < log->result.size(); ++i) { - const AutocompleteMatch& match(log->result.match_at(i)); - const DBCacheKey key = { lower_user_text, match.destination_url }; - - bool is_hit = (i == log->selected_index); - - NetworkActionPredictorDatabase::Row row; - row.user_text = key.user_text; - row.url = key.url; - - DBCacheMap::iterator it = db_cache_.find(key); - if (it == db_cache_.end()) { - row.id = guid::GenerateGUID(); - row.number_of_hits = is_hit ? 1 : 0; - row.number_of_misses = is_hit ? 0 : 1; - - AddRow(key, row); - } else { - DCHECK(db_id_cache_.find(key) != db_id_cache_.end()); - row.id = db_id_cache_.find(key)->second; - row.number_of_hits = it->second.number_of_hits + (is_hit ? 1 : 0); - row.number_of_misses = it->second.number_of_misses + (is_hit ? 0 : 1); - - UpdateRow(it, row); - } - } - CommitTransaction(); + + // TODO(dominich): This doesn't need to be synchronous. Investigate + // posting it as a task to be run later. + OnOmniboxOpenedUrl(*content::Details<AutocompleteLog>(details).ptr()); break; } @@ -278,6 +285,68 @@ void NetworkActionPredictor::Observe( } } +void NetworkActionPredictor::OnOmniboxOpenedUrl(const AutocompleteLog& log) { + if (log.text.length() < kMinimumUserTextLength) + return; + + const GURL& opened_url = + log.result.match_at(log.selected_index).destination_url; + + const string16 lower_user_text(base::i18n::ToLower(log.text)); + + // Add the current match as the only transitional match. + if (prerender::GetOmniboxHeuristicToUse() != + prerender::OMNIBOX_HEURISTIC_EXACT_FULL) { + DCHECK(transitional_matches_.empty()); + TransitionalMatch dummy_match; + dummy_match.user_text = lower_user_text; + dummy_match.urls.push_back(opened_url); + transitional_matches_.push_back(dummy_match); + } + + BeginTransaction(); + // Traverse transitional matches for those that have a user_text that is a + // prefix of |lower_user_text|. + for (std::vector<TransitionalMatch>::const_iterator it = + transitional_matches_.begin(); it != transitional_matches_.end(); + ++it) { + if (!StartsWith(lower_user_text, it->user_text, true)) + continue; + + // Add entries to the database for those matches. + for (std::vector<GURL>::const_iterator url_it = it->urls.begin(); + url_it != it->urls.end(); ++url_it) { + DCHECK(it->user_text.length() >= kMinimumUserTextLength); + const DBCacheKey key = { it->user_text, *url_it }; + const bool is_hit = (*url_it == opened_url); + + NetworkActionPredictorDatabase::Row row; + row.user_text = key.user_text; + row.url = key.url; + + DBCacheMap::iterator it = db_cache_.find(key); + if (it == db_cache_.end()) { + row.id = guid::GenerateGUID(); + row.number_of_hits = is_hit ? 1 : 0; + row.number_of_misses = is_hit ? 0 : 1; + + AddRow(key, row); + } else { + DCHECK(db_id_cache_.find(key) != db_id_cache_.end()); + row.id = db_id_cache_.find(key)->second; + row.number_of_hits = it->second.number_of_hits + (is_hit ? 1 : 0); + row.number_of_misses = it->second.number_of_misses + (is_hit ? 0 : 1); + + UpdateRow(it, row); + } + } + } + CommitTransaction(); + + ClearTransitionalMatches(); +} + + void NetworkActionPredictor::DeleteOldIdsFromCaches( history::URLDatabase* url_db, std::vector<NetworkActionPredictorDatabase::Row::Id>* id_list) { @@ -449,3 +518,9 @@ void NetworkActionPredictor::CommitTransaction() { content::BrowserThread::PostTask(content::BrowserThread::DB, FROM_HERE, base::Bind(&NetworkActionPredictorDatabase::CommitTransaction, db_)); } + +NetworkActionPredictor::TransitionalMatch::TransitionalMatch() { +} + +NetworkActionPredictor::TransitionalMatch::~TransitionalMatch() { +} diff --git a/chrome/browser/autocomplete/network_action_predictor.h b/chrome/browser/autocomplete/network_action_predictor.h index 60d710a..20b5708 100644 --- a/chrome/browser/autocomplete/network_action_predictor.h +++ b/chrome/browser/autocomplete/network_action_predictor.h @@ -17,7 +17,9 @@ #include "content/public/browser/notification_registrar.h" #include "googleurl/src/gurl.h" +struct AutocompleteLog; struct AutocompleteMatch; +class AutocompleteResult; class HistoryService; class Profile; @@ -47,6 +49,16 @@ class NetworkActionPredictor explicit NetworkActionPredictor(Profile* profile); virtual ~NetworkActionPredictor(); + // Registers an AutocompleteResult for a given |user_text|. This will be used + // when the user navigates from the Omnibox to determine early opportunities + // to predict their actions. + void RegisterTransitionalMatches(const string16& user_text, + const AutocompleteResult& result); + + // Clears any transitional matches that have been registered. Called when, for + // example, the AutocompleteEditModel is reverted. + void ClearTransitionalMatches(); + // 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 @@ -63,6 +75,18 @@ class NetworkActionPredictor private: friend class NetworkActionPredictorTest; + struct TransitionalMatch { + TransitionalMatch(); + ~TransitionalMatch(); + + string16 user_text; + std::vector<GURL> urls; + + bool operator==(const string16& other_user_text) const { + return user_text == other_user_text; + } + }; + struct DBCacheKey { string16 user_text; GURL url; @@ -93,6 +117,9 @@ class NetworkActionPredictor const content::NotificationSource& source, const content::NotificationDetails& details) OVERRIDE; + // Called when NOTIFICATION_OMNIBOX_OPENED_URL is observed. + void OnOmniboxOpenedUrl(const AutocompleteLog& log); + // Deletes any old or invalid entries from the local caches. |url_db| and // |id_list| must not be NULL. Every row id deleted will be added to id_list. void DeleteOldIdsFromCaches( @@ -140,6 +167,9 @@ class NetworkActionPredictor scoped_refptr<NetworkActionPredictorDatabase> db_; content::NotificationRegistrar notification_registrar_; + // This is cleared after every Omnibox navigation. + std::vector<TransitionalMatch> transitional_matches_; + DBCacheMap db_cache_; DBIdCacheMap db_id_cache_; |