| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/autocomplete/network_action_predictor.h" | 5 #include "chrome/browser/predictors/autocomplete_action_predictor.h" |
| 6 | 6 |
| 7 #include <math.h> | 7 #include <math.h> |
| 8 | 8 |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/i18n/case_conversion.h" | 12 #include "base/i18n/case_conversion.h" |
| 13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
| 14 #include "base/string_util.h" | 14 #include "base/string_util.h" |
| 15 #include "base/stringprintf.h" | 15 #include "base/stringprintf.h" |
| 16 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
| 17 #include "chrome/browser/autocomplete/autocomplete.h" | 17 #include "chrome/browser/autocomplete/autocomplete.h" |
| 18 #include "chrome/browser/autocomplete/autocomplete_match.h" | 18 #include "chrome/browser/autocomplete/autocomplete_match.h" |
| 19 #include "chrome/browser/autocomplete/network_action_predictor_database.h" | |
| 20 #include "chrome/browser/history/history.h" | 19 #include "chrome/browser/history/history.h" |
| 21 #include "chrome/browser/history/history_notifications.h" | 20 #include "chrome/browser/history/history_notifications.h" |
| 22 #include "chrome/browser/history/in_memory_database.h" | 21 #include "chrome/browser/history/in_memory_database.h" |
| 22 #include "chrome/browser/predictors/predictor_database.h" |
| 23 #include "chrome/browser/predictors/predictor_database_factory.h" |
| 23 #include "chrome/browser/prerender/prerender_field_trial.h" | 24 #include "chrome/browser/prerender/prerender_field_trial.h" |
| 24 #include "chrome/browser/prerender/prerender_manager.h" | 25 #include "chrome/browser/prerender/prerender_manager.h" |
| 25 #include "chrome/browser/prerender/prerender_manager_factory.h" | 26 #include "chrome/browser/prerender/prerender_manager_factory.h" |
| 26 #include "chrome/browser/profiles/profile.h" | 27 #include "chrome/browser/profiles/profile.h" |
| 27 #include "chrome/common/chrome_notification_types.h" | 28 #include "chrome/common/chrome_notification_types.h" |
| 28 #include "chrome/common/guid.h" | 29 #include "chrome/common/guid.h" |
| 29 #include "content/public/browser/browser_thread.h" | 30 #include "content/public/browser/browser_thread.h" |
| 30 #include "content/public/browser/notification_details.h" | 31 #include "content/public/browser/notification_details.h" |
| 31 #include "content/public/browser/notification_service.h" | 32 #include "content/public/browser/notification_service.h" |
| 32 #include "content/public/browser/notification_source.h" | 33 #include "content/public/browser/notification_source.h" |
| 33 | 34 |
| 34 namespace { | 35 namespace { |
| 35 | 36 |
| 36 const float kConfidenceCutoff[] = { | 37 const float kConfidenceCutoff[] = { |
| 37 0.8f, | 38 0.8f, |
| 38 0.5f | 39 0.5f |
| 39 }; | 40 }; |
| 40 | 41 |
| 41 const size_t kMinimumUserTextLength = 1; | 42 const size_t kMinimumUserTextLength = 1; |
| 42 const int kMinimumNumberOfHits = 3; | 43 const int kMinimumNumberOfHits = 3; |
| 43 | 44 |
| 44 COMPILE_ASSERT(arraysize(kConfidenceCutoff) == | 45 COMPILE_ASSERT(arraysize(kConfidenceCutoff) == |
| 45 NetworkActionPredictor::LAST_PREDICT_ACTION, | 46 predictors::AutocompleteActionPredictor::LAST_PREDICT_ACTION, |
| 46 ConfidenceCutoff_count_mismatch); | 47 ConfidenceCutoff_count_mismatch); |
| 47 | 48 |
| 48 enum DatabaseAction { | 49 enum DatabaseAction { |
| 49 DATABASE_ACTION_ADD, | 50 DATABASE_ACTION_ADD, |
| 50 DATABASE_ACTION_UPDATE, | 51 DATABASE_ACTION_UPDATE, |
| 51 DATABASE_ACTION_DELETE_SOME, | 52 DATABASE_ACTION_DELETE_SOME, |
| 52 DATABASE_ACTION_DELETE_ALL, | 53 DATABASE_ACTION_DELETE_ALL, |
| 53 DATABASE_ACTION_COUNT | 54 DATABASE_ACTION_COUNT |
| 54 }; | 55 }; |
| 55 | 56 |
| 56 } | 57 } // namespace |
| 57 | 58 |
| 58 const int NetworkActionPredictor::kMaximumDaysToKeepEntry = 14; | 59 namespace predictors { |
| 59 | 60 |
| 60 double NetworkActionPredictor::hit_weight_ = 1.0; | 61 const int AutocompleteActionPredictor::kMaximumDaysToKeepEntry = 14; |
| 61 | 62 |
| 62 NetworkActionPredictor::NetworkActionPredictor(Profile* profile) | 63 double AutocompleteActionPredictor::hit_weight_ = 1.0; |
| 64 |
| 65 AutocompleteActionPredictor::AutocompleteActionPredictor(Profile* profile) |
| 63 : profile_(profile), | 66 : profile_(profile), |
| 64 db_(new NetworkActionPredictorDatabase(profile)), | 67 db_(PredictorDatabaseFactory::GetForProfile( |
| 68 profile)->autocomplete_table()), |
| 65 initialized_(false) { | 69 initialized_(false) { |
| 66 content::BrowserThread::PostTask(content::BrowserThread::DB, FROM_HERE, | |
| 67 base::Bind(&NetworkActionPredictorDatabase::Initialize, db_)); | |
| 68 | |
| 69 // Request the in-memory database from the history to force it to load so it's | 70 // Request the in-memory database from the history to force it to load so it's |
| 70 // available as soon as possible. | 71 // available as soon as possible. |
| 71 HistoryService* history_service = | 72 HistoryService* history_service = |
| 72 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); | 73 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); |
| 73 if (history_service) | 74 if (history_service) |
| 74 history_service->InMemoryDatabase(); | 75 history_service->InMemoryDatabase(); |
| 75 | 76 |
| 76 // Create local caches using the database as loaded. We will garbage collect | 77 // Create local caches using the database as loaded. We will garbage collect |
| 77 // rows from the caches and the database once the history service is | 78 // rows from the caches and the database once the history service is |
| 78 // available. | 79 // available. |
| 79 std::vector<NetworkActionPredictorDatabase::Row>* rows = | 80 std::vector<AutocompleteActionPredictorTable::Row>* rows = |
| 80 new std::vector<NetworkActionPredictorDatabase::Row>(); | 81 new std::vector<AutocompleteActionPredictorTable::Row>(); |
| 81 content::BrowserThread::PostTaskAndReply( | 82 content::BrowserThread::PostTaskAndReply( |
| 82 content::BrowserThread::DB, FROM_HERE, | 83 content::BrowserThread::DB, FROM_HERE, |
| 83 base::Bind(&NetworkActionPredictorDatabase::GetAllRows, db_, rows), | 84 base::Bind(&AutocompleteActionPredictorTable::GetAllRows, |
| 84 base::Bind(&NetworkActionPredictor::CreateCaches, AsWeakPtr(), | 85 db_, |
| 86 rows), |
| 87 base::Bind(&AutocompleteActionPredictor::CreateCaches, AsWeakPtr(), |
| 85 base::Owned(rows))); | 88 base::Owned(rows))); |
| 86 | |
| 87 } | 89 } |
| 88 | 90 |
| 89 NetworkActionPredictor::~NetworkActionPredictor() { | 91 AutocompleteActionPredictor::~AutocompleteActionPredictor() { |
| 90 } | 92 } |
| 91 | 93 |
| 92 void NetworkActionPredictor::RegisterTransitionalMatches( | 94 void AutocompleteActionPredictor::RegisterTransitionalMatches( |
| 93 const string16& user_text, | 95 const string16& user_text, |
| 94 const AutocompleteResult& result) { | 96 const AutocompleteResult& result) { |
| 95 if (user_text.length() < kMinimumUserTextLength) | 97 if (user_text.length() < kMinimumUserTextLength) |
| 96 return; | 98 return; |
| 97 const string16 lower_user_text(base::i18n::ToLower(user_text)); | 99 const string16 lower_user_text(base::i18n::ToLower(user_text)); |
| 98 | 100 |
| 99 // Merge this in to an existing match if we already saw |user_text| | 101 // Merge this in to an existing match if we already saw |user_text| |
| 100 std::vector<TransitionalMatch>::iterator match_it = | 102 std::vector<TransitionalMatch>::iterator match_it = |
| 101 std::find(transitional_matches_.begin(), transitional_matches_.end(), | 103 std::find(transitional_matches_.begin(), transitional_matches_.end(), |
| 102 lower_user_text); | 104 lower_user_text); |
| 103 | 105 |
| 104 if (match_it == transitional_matches_.end()) { | 106 if (match_it == transitional_matches_.end()) { |
| 105 TransitionalMatch transitional_match; | 107 TransitionalMatch transitional_match; |
| 106 transitional_match.user_text = lower_user_text; | 108 transitional_match.user_text = lower_user_text; |
| 107 match_it = transitional_matches_.insert(transitional_matches_.end(), | 109 match_it = transitional_matches_.insert(transitional_matches_.end(), |
| 108 transitional_match); | 110 transitional_match); |
| 109 } | 111 } |
| 110 | 112 |
| 111 for (AutocompleteResult::const_iterator it = result.begin(); | 113 for (AutocompleteResult::const_iterator it = result.begin(); |
| 112 it != result.end(); ++it) { | 114 it != result.end(); ++it) { |
| 113 if (std::find(match_it->urls.begin(), match_it->urls.end(), | 115 if (std::find(match_it->urls.begin(), match_it->urls.end(), |
| 114 it->destination_url) == match_it->urls.end()) { | 116 it->destination_url) == match_it->urls.end()) { |
| 115 match_it->urls.push_back(it->destination_url); | 117 match_it->urls.push_back(it->destination_url); |
| 116 } | 118 } |
| 117 } | 119 } |
| 118 } | 120 } |
| 119 | 121 |
| 120 void NetworkActionPredictor::ClearTransitionalMatches() { | 122 void AutocompleteActionPredictor::ClearTransitionalMatches() { |
| 121 transitional_matches_.clear(); | 123 transitional_matches_.clear(); |
| 122 } | 124 } |
| 123 | 125 |
| 124 // Given a match, return a recommended action. | 126 // Given a match, return a recommended action. |
| 125 NetworkActionPredictor::Action NetworkActionPredictor::RecommendAction( | 127 AutocompleteActionPredictor::Action |
| 126 const string16& user_text, | 128 AutocompleteActionPredictor::RecommendAction( |
| 127 const AutocompleteMatch& match) const { | 129 const string16& user_text, |
| 130 const AutocompleteMatch& match) const { |
| 128 bool is_in_db = false; | 131 bool is_in_db = false; |
| 129 const double confidence = CalculateConfidence(user_text, match, &is_in_db); | 132 const double confidence = CalculateConfidence(user_text, match, &is_in_db); |
| 130 DCHECK(confidence >= 0.0 && confidence <= 1.0); | 133 DCHECK(confidence >= 0.0 && confidence <= 1.0); |
| 131 | 134 |
| 132 UMA_HISTOGRAM_BOOLEAN("NetworkActionPredictor.MatchIsInDb", is_in_db); | 135 UMA_HISTOGRAM_BOOLEAN("AutocompleteActionPredictor.MatchIsInDb", is_in_db); |
| 133 | 136 |
| 134 if (is_in_db) { | 137 if (is_in_db) { |
| 135 // Multiple enties with the same URL are fine as the confidence may be | 138 // Multiple enties with the same URL are fine as the confidence may be |
| 136 // different. | 139 // different. |
| 137 tracked_urls_.push_back(std::make_pair(match.destination_url, confidence)); | 140 tracked_urls_.push_back(std::make_pair(match.destination_url, confidence)); |
| 138 UMA_HISTOGRAM_COUNTS_100("NetworkActionPredictor.Confidence", | 141 UMA_HISTOGRAM_COUNTS_100("AutocompleteActionPredictor.Confidence", |
| 139 confidence * 100); | 142 confidence * 100); |
| 140 } | 143 } |
| 141 | 144 |
| 142 // Map the confidence to an action. | 145 // Map the confidence to an action. |
| 143 Action action = ACTION_NONE; | 146 Action action = ACTION_NONE; |
| 144 for (int i = 0; i < LAST_PREDICT_ACTION; ++i) { | 147 for (int i = 0; i < LAST_PREDICT_ACTION; ++i) { |
| 145 if (confidence >= kConfidenceCutoff[i]) { | 148 if (confidence >= kConfidenceCutoff[i]) { |
| 146 action = static_cast<Action>(i); | 149 action = static_cast<Action>(i); |
| 147 break; | 150 break; |
| 148 } | 151 } |
| 149 } | 152 } |
| 150 | 153 |
| 151 // Downgrade prerender to preconnect if this is a search match or if omnibox | 154 // Downgrade prerender to preconnect if this is a search match or if omnibox |
| 152 // prerendering is disabled. | 155 // prerendering is disabled. |
| 153 if (action == ACTION_PRERENDER && !prerender::IsOmniboxEnabled(profile_)) | 156 if (action == ACTION_PRERENDER && !prerender::IsOmniboxEnabled(profile_)) |
| 154 action = ACTION_PRECONNECT; | 157 action = ACTION_PRECONNECT; |
| 155 | 158 |
| 156 return action; | 159 return action; |
| 157 } | 160 } |
| 158 | 161 |
| 159 // Return true if the suggestion type warrants a TCP/IP preconnection. | 162 // Return true if the suggestion type warrants a TCP/IP preconnection. |
| 160 // i.e., it is now quite likely that the user will select the related domain. | 163 // i.e., it is now quite likely that the user will select the related domain. |
| 161 // static | 164 // static |
| 162 bool NetworkActionPredictor::IsPreconnectable(const AutocompleteMatch& match) { | 165 bool AutocompleteActionPredictor::IsPreconnectable( |
| 166 const AutocompleteMatch& match) { |
| 163 switch (match.type) { | 167 switch (match.type) { |
| 164 // Matches using the user's default search engine. | 168 // Matches using the user's default search engine. |
| 165 case AutocompleteMatch::SEARCH_WHAT_YOU_TYPED: | 169 case AutocompleteMatch::SEARCH_WHAT_YOU_TYPED: |
| 166 case AutocompleteMatch::SEARCH_HISTORY: | 170 case AutocompleteMatch::SEARCH_HISTORY: |
| 167 case AutocompleteMatch::SEARCH_SUGGEST: | 171 case AutocompleteMatch::SEARCH_SUGGEST: |
| 168 // A match that uses a non-default search engine (e.g. for tab-to-search). | 172 // A match that uses a non-default search engine (e.g. for tab-to-search). |
| 169 case AutocompleteMatch::SEARCH_OTHER_ENGINE: | 173 case AutocompleteMatch::SEARCH_OTHER_ENGINE: |
| 170 return true; | 174 return true; |
| 171 | 175 |
| 172 default: | 176 default: |
| 173 return false; | 177 return false; |
| 174 } | 178 } |
| 175 } | 179 } |
| 176 | 180 |
| 177 void NetworkActionPredictor::Shutdown() { | 181 void AutocompleteActionPredictor::Shutdown() { |
| 178 db_->OnPredictorDestroyed(); | |
| 179 } | 182 } |
| 180 | 183 |
| 181 void NetworkActionPredictor::Observe( | 184 void AutocompleteActionPredictor::Observe( |
| 182 int type, | 185 int type, |
| 183 const content::NotificationSource& source, | 186 const content::NotificationSource& source, |
| 184 const content::NotificationDetails& details) { | 187 const content::NotificationDetails& details) { |
| 185 switch (type) { | 188 switch (type) { |
| 186 case chrome::NOTIFICATION_HISTORY_URLS_DELETED: { | 189 case chrome::NOTIFICATION_HISTORY_URLS_DELETED: { |
| 187 DCHECK(initialized_); | 190 DCHECK(initialized_); |
| 188 const content::Details<const history::URLsDeletedDetails> | 191 const content::Details<const history::URLsDeletedDetails> |
| 189 urls_deleted_details = | 192 urls_deleted_details = |
| 190 content::Details<const history::URLsDeletedDetails>(details); | 193 content::Details<const history::URLsDeletedDetails>(details); |
| 191 if (urls_deleted_details->all_history) | 194 if (urls_deleted_details->all_history) |
| (...skipping 24 matching lines...) Expand all Loading... |
| 216 content::Source<Profile>(profile_)); | 219 content::Source<Profile>(profile_)); |
| 217 break; | 220 break; |
| 218 } | 221 } |
| 219 | 222 |
| 220 default: | 223 default: |
| 221 NOTREACHED() << "Unexpected notification observed."; | 224 NOTREACHED() << "Unexpected notification observed."; |
| 222 break; | 225 break; |
| 223 } | 226 } |
| 224 } | 227 } |
| 225 | 228 |
| 226 void NetworkActionPredictor::OnOmniboxOpenedUrl(const AutocompleteLog& log) { | 229 void AutocompleteActionPredictor::OnOmniboxOpenedUrl( |
| 230 const AutocompleteLog& log) { |
| 227 if (log.text.length() < kMinimumUserTextLength) | 231 if (log.text.length() < kMinimumUserTextLength) |
| 228 return; | 232 return; |
| 229 | 233 |
| 230 const AutocompleteMatch& match = log.result.match_at(log.selected_index); | 234 const AutocompleteMatch& match = log.result.match_at(log.selected_index); |
| 231 | 235 |
| 232 UMA_HISTOGRAM_BOOLEAN( | 236 UMA_HISTOGRAM_BOOLEAN( |
| 233 StringPrintf("Prerender.OmniboxNavigationsCouldPrerender_%.1f", | 237 StringPrintf("Prerender.OmniboxNavigationsCouldPrerender_%.1f", |
| 234 get_hit_weight()).c_str(), | 238 get_hit_weight()).c_str(), |
| 235 prerender::IsOmniboxEnabled(profile_)); | 239 prerender::IsOmniboxEnabled(profile_)); |
| 236 | 240 |
| 237 const GURL& opened_url = match.destination_url; | 241 const GURL& opened_url = match.destination_url; |
| 238 | 242 |
| 239 // If the Omnibox triggered a prerender but the URL doesn't match the one the | 243 // If the Omnibox triggered a prerender but the URL doesn't match the one the |
| 240 // user is navigating to, cancel the prerender. | 244 // user is navigating to, cancel the prerender. |
| 241 prerender::PrerenderManager* prerender_manager = | 245 prerender::PrerenderManager* prerender_manager = |
| 242 prerender::PrerenderManagerFactory::GetForProfile(profile_); | 246 prerender::PrerenderManagerFactory::GetForProfile(profile_); |
| 243 // |prerender_manager| can be NULL in incognito mode or if prerendering is | 247 // |prerender_manager| can be NULL in incognito mode or if prerendering is |
| 244 // otherwise disabled. | 248 // otherwise disabled. |
| 245 if (prerender_manager && !prerender_manager->IsPrerendering(opened_url)) | 249 if (prerender_manager && !prerender_manager->IsPrerendering(opened_url)) |
| 246 prerender_manager->CancelOmniboxPrerenders(); | 250 prerender_manager->CancelOmniboxPrerenders(); |
| 247 | 251 |
| 248 const string16 lower_user_text(base::i18n::ToLower(log.text)); | 252 const string16 lower_user_text(base::i18n::ToLower(log.text)); |
| 249 | 253 |
| 250 BeginTransaction(); | |
| 251 // Traverse transitional matches for those that have a user_text that is a | 254 // Traverse transitional matches for those that have a user_text that is a |
| 252 // prefix of |lower_user_text|. | 255 // prefix of |lower_user_text|. |
| 256 std::vector<AutocompleteActionPredictorTable::Row> rows_to_add; |
| 257 std::vector<AutocompleteActionPredictorTable::Row> rows_to_update; |
| 258 |
| 253 for (std::vector<TransitionalMatch>::const_iterator it = | 259 for (std::vector<TransitionalMatch>::const_iterator it = |
| 254 transitional_matches_.begin(); it != transitional_matches_.end(); | 260 transitional_matches_.begin(); it != transitional_matches_.end(); |
| 255 ++it) { | 261 ++it) { |
| 256 if (!StartsWith(lower_user_text, it->user_text, true)) | 262 if (!StartsWith(lower_user_text, it->user_text, true)) |
| 257 continue; | 263 continue; |
| 258 | 264 |
| 259 // Add entries to the database for those matches. | 265 // Add entries to the database for those matches. |
| 260 for (std::vector<GURL>::const_iterator url_it = it->urls.begin(); | 266 for (std::vector<GURL>::const_iterator url_it = it->urls.begin(); |
| 261 url_it != it->urls.end(); ++url_it) { | 267 url_it != it->urls.end(); ++url_it) { |
| 262 DCHECK(it->user_text.length() >= kMinimumUserTextLength); | 268 DCHECK(it->user_text.length() >= kMinimumUserTextLength); |
| 263 const DBCacheKey key = { it->user_text, *url_it }; | 269 const DBCacheKey key = { it->user_text, *url_it }; |
| 264 const bool is_hit = (*url_it == opened_url); | 270 const bool is_hit = (*url_it == opened_url); |
| 265 | 271 |
| 266 NetworkActionPredictorDatabase::Row row; | 272 AutocompleteActionPredictorTable::Row row; |
| 267 row.user_text = key.user_text; | 273 row.user_text = key.user_text; |
| 268 row.url = key.url; | 274 row.url = key.url; |
| 269 | 275 |
| 270 DBCacheMap::iterator it = db_cache_.find(key); | 276 DBCacheMap::iterator it = db_cache_.find(key); |
| 271 if (it == db_cache_.end()) { | 277 if (it == db_cache_.end()) { |
| 272 row.id = guid::GenerateGUID(); | 278 row.id = guid::GenerateGUID(); |
| 273 row.number_of_hits = is_hit ? 1 : 0; | 279 row.number_of_hits = is_hit ? 1 : 0; |
| 274 row.number_of_misses = is_hit ? 0 : 1; | 280 row.number_of_misses = is_hit ? 0 : 1; |
| 275 | 281 |
| 276 AddRow(key, row); | 282 DBCacheValue value = { row.number_of_hits, row.number_of_misses }; |
| 283 db_cache_[key] = value; |
| 284 db_id_cache_[key] = row.id; |
| 285 |
| 286 rows_to_add.push_back(row); |
| 287 UMA_HISTOGRAM_ENUMERATION( |
| 288 "AutocompleteActionPredictor.DatabaseAction", |
| 289 DATABASE_ACTION_ADD, DATABASE_ACTION_COUNT); |
| 277 } else { | 290 } else { |
| 278 DCHECK(db_id_cache_.find(key) != db_id_cache_.end()); | 291 DCHECK(db_id_cache_.find(key) != db_id_cache_.end()); |
| 279 row.id = db_id_cache_.find(key)->second; | 292 row.id = db_id_cache_.find(key)->second; |
| 280 row.number_of_hits = it->second.number_of_hits + (is_hit ? 1 : 0); | 293 row.number_of_hits = it->second.number_of_hits + (is_hit ? 1 : 0); |
| 281 row.number_of_misses = it->second.number_of_misses + (is_hit ? 0 : 1); | 294 row.number_of_misses = it->second.number_of_misses + (is_hit ? 0 : 1); |
| 282 | 295 |
| 283 UpdateRow(it, row); | 296 it->second.number_of_hits = row.number_of_hits; |
| 297 it->second.number_of_misses = row.number_of_misses; |
| 298 |
| 299 rows_to_update.push_back(row); |
| 300 UMA_HISTOGRAM_ENUMERATION( |
| 301 "AutocompleteActionPredictor.DatabaseAction", |
| 302 DATABASE_ACTION_UPDATE, DATABASE_ACTION_COUNT); |
| 284 } | 303 } |
| 285 } | 304 } |
| 286 } | 305 } |
| 287 CommitTransaction(); | 306 if (rows_to_add.size() > 0 || rows_to_update.size() > 0) |
| 307 content::BrowserThread::PostTask(content::BrowserThread::DB, FROM_HERE, |
| 308 base::Bind(&AutocompleteActionPredictorTable::AddAndUpdateRows, |
| 309 db_, |
| 310 rows_to_add, |
| 311 rows_to_update)); |
| 288 | 312 |
| 289 ClearTransitionalMatches(); | 313 ClearTransitionalMatches(); |
| 290 | 314 |
| 291 // Check against tracked urls and log accuracy for the confidence we | 315 // Check against tracked urls and log accuracy for the confidence we |
| 292 // predicted. | 316 // predicted. |
| 293 for (std::vector<std::pair<GURL, double> >::const_iterator it = | 317 for (std::vector<std::pair<GURL, double> >::const_iterator it = |
| 294 tracked_urls_.begin(); it != tracked_urls_.end(); | 318 tracked_urls_.begin(); it != tracked_urls_.end(); |
| 295 ++it) { | 319 ++it) { |
| 296 if (opened_url == it->first) { | 320 if (opened_url == it->first) { |
| 297 UMA_HISTOGRAM_COUNTS_100("NetworkActionPredictor.AccurateCount", | 321 UMA_HISTOGRAM_COUNTS_100("AutocompleteActionPredictor.AccurateCount", |
| 298 it->second * 100); | 322 it->second * 100); |
| 299 } | 323 } |
| 300 } | 324 } |
| 301 tracked_urls_.clear(); | 325 tracked_urls_.clear(); |
| 302 } | 326 } |
| 303 | 327 |
| 304 void NetworkActionPredictor::DeleteOldIdsFromCaches( | 328 void AutocompleteActionPredictor::DeleteOldIdsFromCaches( |
| 305 history::URLDatabase* url_db, | 329 history::URLDatabase* url_db, |
| 306 std::vector<NetworkActionPredictorDatabase::Row::Id>* id_list) { | 330 std::vector<AutocompleteActionPredictorTable::Row::Id>* id_list) { |
| 307 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 331 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 308 DCHECK(url_db); | 332 DCHECK(url_db); |
| 309 DCHECK(id_list); | 333 DCHECK(id_list); |
| 310 id_list->clear(); | 334 id_list->clear(); |
| 311 for (DBCacheMap::iterator it = db_cache_.begin(); it != db_cache_.end();) { | 335 for (DBCacheMap::iterator it = db_cache_.begin(); it != db_cache_.end();) { |
| 312 history::URLRow url_row; | 336 history::URLRow url_row; |
| 313 | 337 |
| 314 if ((url_db->GetRowForURL(it->first.url, &url_row) == 0) || | 338 if ((url_db->GetRowForURL(it->first.url, &url_row) == 0) || |
| 315 ((base::Time::Now() - url_row.last_visit()).InDays() > | 339 ((base::Time::Now() - url_row.last_visit()).InDays() > |
| 316 kMaximumDaysToKeepEntry)) { | 340 kMaximumDaysToKeepEntry)) { |
| 317 const DBIdCacheMap::iterator id_it = db_id_cache_.find(it->first); | 341 const DBIdCacheMap::iterator id_it = db_id_cache_.find(it->first); |
| 318 DCHECK(id_it != db_id_cache_.end()); | 342 DCHECK(id_it != db_id_cache_.end()); |
| 319 id_list->push_back(id_it->second); | 343 id_list->push_back(id_it->second); |
| 320 db_id_cache_.erase(id_it); | 344 db_id_cache_.erase(id_it); |
| 321 db_cache_.erase(it++); | 345 db_cache_.erase(it++); |
| 322 } else { | 346 } else { |
| 323 ++it; | 347 ++it; |
| 324 } | 348 } |
| 325 } | 349 } |
| 326 } | 350 } |
| 327 | 351 |
| 328 void NetworkActionPredictor::DeleteOldEntries(history::URLDatabase* url_db) { | 352 void AutocompleteActionPredictor::DeleteOldEntries( |
| 353 history::URLDatabase* url_db) { |
| 329 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 354 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 330 DCHECK(!initialized_); | 355 DCHECK(!initialized_); |
| 331 | 356 |
| 332 std::vector<NetworkActionPredictorDatabase::Row::Id> ids_to_delete; | 357 std::vector<AutocompleteActionPredictorTable::Row::Id> ids_to_delete; |
| 333 DeleteOldIdsFromCaches(url_db, &ids_to_delete); | 358 DeleteOldIdsFromCaches(url_db, &ids_to_delete); |
| 334 | 359 |
| 335 content::BrowserThread::PostTask(content::BrowserThread::DB, FROM_HERE, | 360 content::BrowserThread::PostTask(content::BrowserThread::DB, FROM_HERE, |
| 336 base::Bind(&NetworkActionPredictorDatabase::DeleteRows, db_, | 361 base::Bind(&AutocompleteActionPredictorTable::DeleteRows, |
| 362 db_, |
| 337 ids_to_delete)); | 363 ids_to_delete)); |
| 338 | 364 |
| 339 // Register for notifications and set the |initialized_| flag. | 365 // Register for notifications and set the |initialized_| flag. |
| 340 notification_registrar_.Add(this, chrome::NOTIFICATION_OMNIBOX_OPENED_URL, | 366 notification_registrar_.Add(this, chrome::NOTIFICATION_OMNIBOX_OPENED_URL, |
| 341 content::Source<Profile>(profile_)); | 367 content::Source<Profile>(profile_)); |
| 342 notification_registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, | 368 notification_registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, |
| 343 content::Source<Profile>(profile_)); | 369 content::Source<Profile>(profile_)); |
| 344 initialized_ = true; | 370 initialized_ = true; |
| 345 } | 371 } |
| 346 | 372 |
| 347 void NetworkActionPredictor::CreateCaches( | 373 void AutocompleteActionPredictor::CreateCaches( |
| 348 std::vector<NetworkActionPredictorDatabase::Row>* rows) { | 374 std::vector<AutocompleteActionPredictorTable::Row>* rows) { |
| 349 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 375 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 350 DCHECK(!initialized_); | 376 DCHECK(!initialized_); |
| 351 DCHECK(db_cache_.empty()); | 377 DCHECK(db_cache_.empty()); |
| 352 DCHECK(db_id_cache_.empty()); | 378 DCHECK(db_id_cache_.empty()); |
| 353 | 379 |
| 354 for (std::vector<NetworkActionPredictorDatabase::Row>::const_iterator it = | 380 for (std::vector<AutocompleteActionPredictorTable::Row>::const_iterator it = |
| 355 rows->begin(); it != rows->end(); ++it) { | 381 rows->begin(); it != rows->end(); ++it) { |
| 356 const DBCacheKey key = { it->user_text, it->url }; | 382 const DBCacheKey key = { it->user_text, it->url }; |
| 357 const DBCacheValue value = { it->number_of_hits, it->number_of_misses }; | 383 const DBCacheValue value = { it->number_of_hits, it->number_of_misses }; |
| 358 db_cache_[key] = value; | 384 db_cache_[key] = value; |
| 359 db_id_cache_[key] = it->id; | 385 db_id_cache_[key] = it->id; |
| 360 } | 386 } |
| 361 | 387 |
| 362 // If the history service is ready, delete any old or invalid entries. | 388 // If the history service is ready, delete any old or invalid entries. |
| 363 HistoryService* history_service = | 389 HistoryService* history_service = |
| 364 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); | 390 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); |
| 365 if (!TryDeleteOldEntries(history_service)) { | 391 if (!TryDeleteOldEntries(history_service)) { |
| 366 // Wait for the notification that the history service is ready and the URL | 392 // Wait for the notification that the history service is ready and the URL |
| 367 // DB is loaded. | 393 // DB is loaded. |
| 368 notification_registrar_.Add(this, chrome::NOTIFICATION_HISTORY_LOADED, | 394 notification_registrar_.Add(this, chrome::NOTIFICATION_HISTORY_LOADED, |
| 369 content::Source<Profile>(profile_)); | 395 content::Source<Profile>(profile_)); |
| 370 } | 396 } |
| 371 } | 397 } |
| 372 | 398 |
| 373 bool NetworkActionPredictor::TryDeleteOldEntries(HistoryService* service) { | 399 bool AutocompleteActionPredictor::TryDeleteOldEntries(HistoryService* service) { |
| 374 if (!service) | 400 if (!service) |
| 375 return false; | 401 return false; |
| 376 | 402 |
| 377 history::URLDatabase* url_db = service->InMemoryDatabase(); | 403 history::URLDatabase* url_db = service->InMemoryDatabase(); |
| 378 if (!url_db) | 404 if (!url_db) |
| 379 return false; | 405 return false; |
| 380 | 406 |
| 381 DeleteOldEntries(url_db); | 407 DeleteOldEntries(url_db); |
| 382 return true; | 408 return true; |
| 383 } | 409 } |
| 384 | 410 |
| 385 double NetworkActionPredictor::CalculateConfidence( | 411 double AutocompleteActionPredictor::CalculateConfidence( |
| 386 const string16& user_text, | 412 const string16& user_text, |
| 387 const AutocompleteMatch& match, | 413 const AutocompleteMatch& match, |
| 388 bool* is_in_db) const { | 414 bool* is_in_db) const { |
| 389 const DBCacheKey key = { user_text, match.destination_url }; | 415 const DBCacheKey key = { user_text, match.destination_url }; |
| 390 | 416 |
| 391 *is_in_db = false; | 417 *is_in_db = false; |
| 392 if (user_text.length() < kMinimumUserTextLength) | 418 if (user_text.length() < kMinimumUserTextLength) |
| 393 return 0.0; | 419 return 0.0; |
| 394 | 420 |
| 395 const DBCacheMap::const_iterator iter = db_cache_.find(key); | 421 const DBCacheMap::const_iterator iter = db_cache_.find(key); |
| 396 if (iter == db_cache_.end()) | 422 if (iter == db_cache_.end()) |
| 397 return 0.0; | 423 return 0.0; |
| 398 | 424 |
| 399 *is_in_db = true; | 425 *is_in_db = true; |
| 400 return CalculateConfidenceForDbEntry(iter); | 426 return CalculateConfidenceForDbEntry(iter); |
| 401 } | 427 } |
| 402 | 428 |
| 403 double NetworkActionPredictor::CalculateConfidenceForDbEntry( | 429 double AutocompleteActionPredictor::CalculateConfidenceForDbEntry( |
| 404 DBCacheMap::const_iterator iter) const { | 430 DBCacheMap::const_iterator iter) const { |
| 405 const DBCacheValue& value = iter->second; | 431 const DBCacheValue& value = iter->second; |
| 406 if (value.number_of_hits < kMinimumNumberOfHits) | 432 if (value.number_of_hits < kMinimumNumberOfHits) |
| 407 return 0.0; | 433 return 0.0; |
| 408 | 434 |
| 409 const double number_of_hits = value.number_of_hits * hit_weight_; | 435 const double number_of_hits = value.number_of_hits * hit_weight_; |
| 410 return number_of_hits / (number_of_hits + value.number_of_misses); | 436 return number_of_hits / (number_of_hits + value.number_of_misses); |
| 411 } | 437 } |
| 412 | 438 |
| 413 void NetworkActionPredictor::AddRow( | 439 void AutocompleteActionPredictor::AddRow( |
| 414 const DBCacheKey& key, | 440 const DBCacheKey& key, |
| 415 const NetworkActionPredictorDatabase::Row& row) { | 441 const AutocompleteActionPredictorTable::Row& row) { |
| 416 if (!initialized_) | 442 if (!initialized_) |
| 417 return; | 443 return; |
| 418 | 444 |
| 419 DBCacheValue value = { row.number_of_hits, row.number_of_misses }; | 445 DBCacheValue value = { row.number_of_hits, row.number_of_misses }; |
| 420 db_cache_[key] = value; | 446 db_cache_[key] = value; |
| 421 db_id_cache_[key] = row.id; | 447 db_id_cache_[key] = row.id; |
| 422 content::BrowserThread::PostTask(content::BrowserThread::DB, FROM_HERE, | 448 content::BrowserThread::PostTask(content::BrowserThread::DB, FROM_HERE, |
| 423 base::Bind(&NetworkActionPredictorDatabase::AddRow, db_, row)); | 449 base::Bind(&AutocompleteActionPredictorTable::AddRow, |
| 450 db_, |
| 451 row)); |
| 424 | 452 |
| 425 UMA_HISTOGRAM_ENUMERATION("NetworkActionPredictor.DatabaseAction", | 453 UMA_HISTOGRAM_ENUMERATION("AutocompleteActionPredictor.DatabaseAction", |
| 426 DATABASE_ACTION_ADD, DATABASE_ACTION_COUNT); | 454 DATABASE_ACTION_ADD, DATABASE_ACTION_COUNT); |
| 427 } | 455 } |
| 428 | 456 |
| 429 void NetworkActionPredictor::UpdateRow( | 457 void AutocompleteActionPredictor::UpdateRow( |
| 430 DBCacheMap::iterator it, | 458 DBCacheMap::iterator it, |
| 431 const NetworkActionPredictorDatabase::Row& row) { | 459 const AutocompleteActionPredictorTable::Row& row) { |
| 432 if (!initialized_) | 460 if (!initialized_) |
| 433 return; | 461 return; |
| 434 | 462 |
| 435 DCHECK(it != db_cache_.end()); | 463 DCHECK(it != db_cache_.end()); |
| 436 it->second.number_of_hits = row.number_of_hits; | 464 it->second.number_of_hits = row.number_of_hits; |
| 437 it->second.number_of_misses = row.number_of_misses; | 465 it->second.number_of_misses = row.number_of_misses; |
| 438 content::BrowserThread::PostTask(content::BrowserThread::DB, FROM_HERE, | 466 content::BrowserThread::PostTask(content::BrowserThread::DB, FROM_HERE, |
| 439 base::Bind(&NetworkActionPredictorDatabase::UpdateRow, db_, row)); | 467 base::Bind(&AutocompleteActionPredictorTable::UpdateRow, |
| 440 UMA_HISTOGRAM_ENUMERATION("NetworkActionPredictor.DatabaseAction", | 468 db_, |
| 469 row)); |
| 470 UMA_HISTOGRAM_ENUMERATION("AutocompleteActionPredictor.DatabaseAction", |
| 441 DATABASE_ACTION_UPDATE, DATABASE_ACTION_COUNT); | 471 DATABASE_ACTION_UPDATE, DATABASE_ACTION_COUNT); |
| 442 } | 472 } |
| 443 | 473 |
| 444 void NetworkActionPredictor::DeleteAllRows() { | 474 void AutocompleteActionPredictor::DeleteAllRows() { |
| 445 if (!initialized_) | 475 if (!initialized_) |
| 446 return; | 476 return; |
| 447 | 477 |
| 448 db_cache_.clear(); | 478 db_cache_.clear(); |
| 449 db_id_cache_.clear(); | 479 db_id_cache_.clear(); |
| 450 content::BrowserThread::PostTask(content::BrowserThread::DB, FROM_HERE, | 480 content::BrowserThread::PostTask(content::BrowserThread::DB, FROM_HERE, |
| 451 base::Bind(&NetworkActionPredictorDatabase::DeleteAllRows, db_)); | 481 base::Bind(&AutocompleteActionPredictorTable::DeleteAllRows, |
| 452 UMA_HISTOGRAM_ENUMERATION("NetworkActionPredictor.DatabaseAction", | 482 db_)); |
| 483 UMA_HISTOGRAM_ENUMERATION("AutocompleteActionPredictor.DatabaseAction", |
| 453 DATABASE_ACTION_DELETE_ALL, DATABASE_ACTION_COUNT); | 484 DATABASE_ACTION_DELETE_ALL, DATABASE_ACTION_COUNT); |
| 454 } | 485 } |
| 455 | 486 |
| 456 void NetworkActionPredictor::DeleteRowsWithURLs(const std::set<GURL>& urls) { | 487 void AutocompleteActionPredictor::DeleteRowsWithURLs( |
| 488 const std::set<GURL>& urls) { |
| 457 if (!initialized_) | 489 if (!initialized_) |
| 458 return; | 490 return; |
| 459 | 491 |
| 460 std::vector<NetworkActionPredictorDatabase::Row::Id> id_list; | 492 std::vector<AutocompleteActionPredictorTable::Row::Id> id_list; |
| 461 | 493 |
| 462 for (DBCacheMap::iterator it = db_cache_.begin(); it != db_cache_.end();) { | 494 for (DBCacheMap::iterator it = db_cache_.begin(); it != db_cache_.end();) { |
| 463 if (urls.find(it->first.url) != urls.end()) { | 495 if (urls.find(it->first.url) != urls.end()) { |
| 464 const DBIdCacheMap::iterator id_it = db_id_cache_.find(it->first); | 496 const DBIdCacheMap::iterator id_it = db_id_cache_.find(it->first); |
| 465 DCHECK(id_it != db_id_cache_.end()); | 497 DCHECK(id_it != db_id_cache_.end()); |
| 466 id_list.push_back(id_it->second); | 498 id_list.push_back(id_it->second); |
| 467 db_id_cache_.erase(id_it); | 499 db_id_cache_.erase(id_it); |
| 468 db_cache_.erase(it++); | 500 db_cache_.erase(it++); |
| 469 } else { | 501 } else { |
| 470 ++it; | 502 ++it; |
| 471 } | 503 } |
| 472 } | 504 } |
| 473 | 505 |
| 474 content::BrowserThread::PostTask(content::BrowserThread::DB, FROM_HERE, | 506 content::BrowserThread::PostTask(content::BrowserThread::DB, FROM_HERE, |
| 475 base::Bind(&NetworkActionPredictorDatabase::DeleteRows, db_, id_list)); | 507 base::Bind(&AutocompleteActionPredictorTable::DeleteRows, |
| 476 UMA_HISTOGRAM_ENUMERATION("NetworkActionPredictor.DatabaseAction", | 508 db_, |
| 509 id_list)); |
| 510 UMA_HISTOGRAM_ENUMERATION("AutocompleteActionPredictor.DatabaseAction", |
| 477 DATABASE_ACTION_DELETE_SOME, DATABASE_ACTION_COUNT); | 511 DATABASE_ACTION_DELETE_SOME, DATABASE_ACTION_COUNT); |
| 478 } | 512 } |
| 479 | 513 |
| 480 void NetworkActionPredictor::BeginTransaction() { | 514 AutocompleteActionPredictor::TransitionalMatch::TransitionalMatch() { |
| 481 if (!initialized_) | |
| 482 return; | |
| 483 | |
| 484 content::BrowserThread::PostTask(content::BrowserThread::DB, FROM_HERE, | |
| 485 base::Bind(&NetworkActionPredictorDatabase::BeginTransaction, db_)); | |
| 486 } | 515 } |
| 487 | 516 |
| 488 void NetworkActionPredictor::CommitTransaction() { | 517 AutocompleteActionPredictor::TransitionalMatch::~TransitionalMatch() { |
| 489 if (!initialized_) | |
| 490 return; | |
| 491 | |
| 492 content::BrowserThread::PostTask(content::BrowserThread::DB, FROM_HERE, | |
| 493 base::Bind(&NetworkActionPredictorDatabase::CommitTransaction, db_)); | |
| 494 } | 518 } |
| 495 | 519 |
| 496 NetworkActionPredictor::TransitionalMatch::TransitionalMatch() { | 520 } // namespace predictors |
| 497 } | |
| 498 | |
| 499 NetworkActionPredictor::TransitionalMatch::~TransitionalMatch() { | |
| 500 } | |
| OLD | NEW |