Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/autocomplete/network_action_predictor.h" |
| 6 | 6 |
| 7 #include <math.h> | 7 #include <math.h> |
| 8 | 8 |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 123 base::Bind(&NetworkActionPredictorDatabase::GetAllRows, db_, rows), | 123 base::Bind(&NetworkActionPredictorDatabase::GetAllRows, db_, rows), |
| 124 base::Bind(&NetworkActionPredictor::CreateCaches, AsWeakPtr(), | 124 base::Bind(&NetworkActionPredictor::CreateCaches, AsWeakPtr(), |
| 125 base::Owned(rows))); | 125 base::Owned(rows))); |
| 126 | 126 |
| 127 } | 127 } |
| 128 | 128 |
| 129 NetworkActionPredictor::~NetworkActionPredictor() { | 129 NetworkActionPredictor::~NetworkActionPredictor() { |
| 130 db_->OnPredictorDestroyed(); | 130 db_->OnPredictorDestroyed(); |
| 131 } | 131 } |
| 132 | 132 |
| 133 void NetworkActionPredictor::RegisterTransitionalMatches( | |
| 134 const string16& user_text, | |
| 135 const AutocompleteResult& result) { | |
| 136 if (prerender::GetOmniboxHeuristicToUse() != | |
| 137 prerender::OMNIBOX_HEURISTIC_EXACT_FULL) { | |
| 138 return; | |
| 139 } | |
| 140 if (user_text.length() < kMinimumUserTextLength) | |
| 141 return; | |
| 142 const string16 lower_user_text(base::i18n::ToLower(user_text)); | |
| 143 | |
| 144 // Don't register if we already saw this |user_text|. | |
|
Peter Kasting
2011/11/18 21:17:13
Are you sure this is what you want? It's possible
dominich
2011/11/18 23:05:51
I tested this and although I saw OnChanged being c
| |
| 145 if (std::find(transitional_matches_.begin(), transitional_matches_.end(), | |
| 146 lower_user_text) != transitional_matches_.end()) | |
| 147 return; | |
| 148 | |
| 149 TransitionalMatch transitional_match; | |
| 150 transitional_match.user_text = lower_user_text; | |
| 151 for (AutocompleteResult::const_iterator it = result.begin(); | |
| 152 it != result.end(); ++it) { | |
| 153 transitional_match.urls.push_back(it->destination_url); | |
| 154 } | |
| 155 transitional_matches_.push_back(transitional_match); | |
| 156 } | |
| 157 | |
| 158 void NetworkActionPredictor::ClearTransitionalMatches() { | |
| 159 transitional_matches_.clear(); | |
| 160 } | |
| 161 | |
| 133 // Given a match, return a recommended action. | 162 // Given a match, return a recommended action. |
| 134 NetworkActionPredictor::Action NetworkActionPredictor::RecommendAction( | 163 NetworkActionPredictor::Action NetworkActionPredictor::RecommendAction( |
| 135 const string16& user_text, | 164 const string16& user_text, |
| 136 const AutocompleteMatch& match) const { | 165 const AutocompleteMatch& match) const { |
| 137 double confidence = 0.0; | 166 double confidence = 0.0; |
| 138 | 167 |
| 139 switch (prerender::GetOmniboxHeuristicToUse()) { | 168 switch (prerender::GetOmniboxHeuristicToUse()) { |
| 140 case prerender::OMNIBOX_HEURISTIC_ORIGINAL: { | 169 case prerender::OMNIBOX_HEURISTIC_ORIGINAL: { |
| 141 history::URLRow url_row; | 170 history::URLRow url_row; |
| 142 if (GetURLRowForAutocompleteMatch(profile_, match, &url_row)) | 171 if (GetURLRowForAutocompleteMatch(profile_, match, &url_row)) |
| 143 confidence = OriginalAlgorithm(url_row); | 172 confidence = OriginalAlgorithm(url_row); |
| 144 break; | 173 break; |
| 145 } | 174 } |
| 146 case prerender::OMNIBOX_HEURISTIC_CONSERVATIVE: { | 175 case prerender::OMNIBOX_HEURISTIC_CONSERVATIVE: { |
| 147 history::URLRow url_row; | 176 history::URLRow url_row; |
| 148 if (GetURLRowForAutocompleteMatch(profile_, match, &url_row)) | 177 if (GetURLRowForAutocompleteMatch(profile_, match, &url_row)) |
| 149 confidence = ConservativeAlgorithm(url_row); | 178 confidence = ConservativeAlgorithm(url_row); |
| 150 break; | 179 break; |
| 151 } | 180 } |
| 152 case prerender::OMNIBOX_HEURISTIC_EXACT: | 181 case prerender::OMNIBOX_HEURISTIC_EXACT: |
| 182 case prerender::OMNIBOX_HEURISTIC_EXACT_FULL: | |
| 153 confidence = ExactAlgorithm(user_text, match); | 183 confidence = ExactAlgorithm(user_text, match); |
| 154 break; | 184 break; |
| 155 default: | 185 default: |
| 156 NOTREACHED(); | 186 NOTREACHED(); |
| 157 break; | 187 break; |
| 158 }; | 188 }; |
| 159 | 189 |
| 160 DCHECK(confidence >= 0.0 && confidence <= 1.0); | 190 DCHECK(confidence >= 0.0 && confidence <= 1.0); |
| 161 | 191 |
| 162 UMA_HISTOGRAM_COUNTS_100("NetworkActionPredictor.Confidence_" + | 192 UMA_HISTOGRAM_COUNTS_100("NetworkActionPredictor.Confidence_" + |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 218 else | 248 else |
| 219 DeleteRowsWithURLs(urls_deleted_details->urls); | 249 DeleteRowsWithURLs(urls_deleted_details->urls); |
| 220 break; | 250 break; |
| 221 } | 251 } |
| 222 | 252 |
| 223 // This notification does not catch all instances of the user navigating | 253 // This notification does not catch all instances of the user navigating |
| 224 // from the Omnibox, but it does catch the cases where the dropdown is open | 254 // from the Omnibox, but it does catch the cases where the dropdown is open |
| 225 // and those are the events we're most interested in. | 255 // and those are the events we're most interested in. |
| 226 case chrome::NOTIFICATION_OMNIBOX_OPENED_URL: { | 256 case chrome::NOTIFICATION_OMNIBOX_OPENED_URL: { |
| 227 DCHECK(initialized_); | 257 DCHECK(initialized_); |
| 228 AutocompleteLog* log = content::Details<AutocompleteLog>(details).ptr(); | |
| 229 if (log->text.length() < kMinimumUserTextLength) | |
| 230 break; | |
| 231 | 258 |
| 232 const string16 lower_user_text(base::i18n::ToLower(log->text)); | 259 // TODO(dominich): This doesn't need to be synchronous. Investigate |
| 233 | 260 // posting it as a task to be run later. |
| 234 BeginTransaction(); | 261 OnOmniboxOpenedUrl(*content::Details<AutocompleteLog>(details).ptr()); |
| 235 for (size_t i = 0; i < log->result.size(); ++i) { | |
| 236 const AutocompleteMatch& match(log->result.match_at(i)); | |
| 237 const DBCacheKey key = { lower_user_text, match.destination_url }; | |
| 238 | |
| 239 bool is_hit = (i == log->selected_index); | |
| 240 | |
| 241 NetworkActionPredictorDatabase::Row row; | |
| 242 row.user_text = key.user_text; | |
| 243 row.url = key.url; | |
| 244 | |
| 245 DBCacheMap::iterator it = db_cache_.find(key); | |
| 246 if (it == db_cache_.end()) { | |
| 247 row.id = guid::GenerateGUID(); | |
| 248 row.number_of_hits = is_hit ? 1 : 0; | |
| 249 row.number_of_misses = is_hit ? 0 : 1; | |
| 250 | |
| 251 AddRow(key, row); | |
| 252 } else { | |
| 253 DCHECK(db_id_cache_.find(key) != db_id_cache_.end()); | |
| 254 row.id = db_id_cache_.find(key)->second; | |
| 255 row.number_of_hits = it->second.number_of_hits + (is_hit ? 1 : 0); | |
| 256 row.number_of_misses = it->second.number_of_misses + (is_hit ? 0 : 1); | |
| 257 | |
| 258 UpdateRow(it, row); | |
| 259 } | |
| 260 } | |
| 261 CommitTransaction(); | |
| 262 break; | 262 break; |
| 263 } | 263 } |
| 264 | 264 |
| 265 case chrome::NOTIFICATION_HISTORY_LOADED: { | 265 case chrome::NOTIFICATION_HISTORY_LOADED: { |
| 266 DCHECK(!initialized_); | 266 DCHECK(!initialized_); |
| 267 TryDeleteOldEntries(content::Details<HistoryService>(details).ptr()); | 267 TryDeleteOldEntries(content::Details<HistoryService>(details).ptr()); |
| 268 | 268 |
| 269 notification_registrar_.Remove(this, | 269 notification_registrar_.Remove(this, |
| 270 chrome::NOTIFICATION_HISTORY_LOADED, | 270 chrome::NOTIFICATION_HISTORY_LOADED, |
| 271 content::Source<Profile>(profile_)); | 271 content::Source<Profile>(profile_)); |
| 272 break; | 272 break; |
| 273 } | 273 } |
| 274 | 274 |
| 275 default: | 275 default: |
| 276 NOTREACHED() << "Unexpected notification observed."; | 276 NOTREACHED() << "Unexpected notification observed."; |
| 277 break; | 277 break; |
| 278 } | 278 } |
| 279 } | 279 } |
| 280 | 280 |
| 281 void NetworkActionPredictor::OnOmniboxOpenedUrl(const AutocompleteLog& log) { | |
| 282 if (log.text.length() < kMinimumUserTextLength) | |
| 283 return; | |
| 284 | |
| 285 const GURL& opened_url = | |
| 286 log.result.match_at(log.selected_index).destination_url; | |
| 287 | |
| 288 const string16 lower_user_text(base::i18n::ToLower(log.text)); | |
| 289 | |
| 290 // Add the current match as the only transitional match. | |
| 291 if (prerender::GetOmniboxHeuristicToUse() != | |
| 292 prerender::OMNIBOX_HEURISTIC_EXACT_FULL) { | |
| 293 DCHECK(transitional_matches_.empty()); | |
| 294 TransitionalMatch dummy_match; | |
| 295 dummy_match.user_text = lower_user_text; | |
| 296 dummy_match.urls.push_back(opened_url); | |
| 297 transitional_matches_.push_back(dummy_match); | |
| 298 } | |
| 299 | |
| 300 BeginTransaction(); | |
| 301 // Traverse transitional matches for those that have a user_text that is a | |
| 302 // prefix of |lower_user_text|. | |
| 303 for (std::vector<TransitionalMatch>::const_iterator it = | |
| 304 transitional_matches_.begin(); it != transitional_matches_.end(); | |
| 305 ++it) { | |
| 306 if (!StartsWith(lower_user_text, it->user_text, true)) | |
| 307 continue; | |
| 308 | |
| 309 // Add entries to the database for those matches. | |
| 310 for (std::vector<GURL>::const_iterator url_it = it->urls.begin(); | |
| 311 url_it != it->urls.end(); ++url_it) { | |
| 312 DCHECK(it->user_text.length() >= kMinimumUserTextLength); | |
| 313 const DBCacheKey key = { it->user_text, *url_it }; | |
| 314 const bool is_hit = (*url_it == opened_url); | |
| 315 | |
| 316 NetworkActionPredictorDatabase::Row row; | |
| 317 row.user_text = key.user_text; | |
| 318 row.url = key.url; | |
| 319 | |
| 320 DBCacheMap::iterator it = db_cache_.find(key); | |
| 321 if (it == db_cache_.end()) { | |
| 322 row.id = guid::GenerateGUID(); | |
| 323 row.number_of_hits = is_hit ? 1 : 0; | |
| 324 row.number_of_misses = is_hit ? 0 : 1; | |
|
Peter Kasting
2011/11/18 21:17:13
Nit: Or "= 1 - row.number_of_hits", dunno which is
dominich
2011/11/18 23:05:51
I like the symmetry of the existing code - it's cl
| |
| 325 | |
| 326 AddRow(key, row); | |
| 327 } else { | |
| 328 DCHECK(db_id_cache_.find(key) != db_id_cache_.end()); | |
| 329 row.id = db_id_cache_.find(key)->second; | |
| 330 row.number_of_hits = it->second.number_of_hits + (is_hit ? 1 : 0); | |
| 331 row.number_of_misses = it->second.number_of_misses + (is_hit ? 0 : 1); | |
| 332 | |
| 333 UpdateRow(it, row); | |
| 334 } | |
| 335 } | |
| 336 } | |
| 337 CommitTransaction(); | |
| 338 | |
| 339 ClearTransitionalMatches(); | |
| 340 } | |
| 341 | |
| 342 | |
| 281 void NetworkActionPredictor::DeleteOldIdsFromCaches( | 343 void NetworkActionPredictor::DeleteOldIdsFromCaches( |
| 282 history::URLDatabase* url_db, | 344 history::URLDatabase* url_db, |
| 283 std::vector<NetworkActionPredictorDatabase::Row::Id>* id_list) { | 345 std::vector<NetworkActionPredictorDatabase::Row::Id>* id_list) { |
| 284 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 346 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 285 DCHECK(url_db); | 347 DCHECK(url_db); |
| 286 DCHECK(id_list); | 348 DCHECK(id_list); |
| 287 id_list->clear(); | 349 id_list->clear(); |
| 288 for (DBCacheMap::iterator it = db_cache_.begin(); it != db_cache_.end();) { | 350 for (DBCacheMap::iterator it = db_cache_.begin(); it != db_cache_.end();) { |
| 289 history::URLRow url_row; | 351 history::URLRow url_row; |
| 290 | 352 |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 442 base::Bind(&NetworkActionPredictorDatabase::BeginTransaction, db_)); | 504 base::Bind(&NetworkActionPredictorDatabase::BeginTransaction, db_)); |
| 443 } | 505 } |
| 444 | 506 |
| 445 void NetworkActionPredictor::CommitTransaction() { | 507 void NetworkActionPredictor::CommitTransaction() { |
| 446 if (!initialized_) | 508 if (!initialized_) |
| 447 return; | 509 return; |
| 448 | 510 |
| 449 content::BrowserThread::PostTask(content::BrowserThread::DB, FROM_HERE, | 511 content::BrowserThread::PostTask(content::BrowserThread::DB, FROM_HERE, |
| 450 base::Bind(&NetworkActionPredictorDatabase::CommitTransaction, db_)); | 512 base::Bind(&NetworkActionPredictorDatabase::CommitTransaction, db_)); |
| 451 } | 513 } |
| OLD | NEW |