| 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/autocomplete_controller.h" | 5 #include "chrome/browser/autocomplete/autocomplete_controller.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 if (matches_requested == AutocompleteInput::ALL_MATCHES && | 206 if (matches_requested == AutocompleteInput::ALL_MATCHES && |
| 207 (text.length() < 6)) { | 207 (text.length() < 6)) { |
| 208 base::TimeTicks end_time = base::TimeTicks::Now(); | 208 base::TimeTicks end_time = base::TimeTicks::Now(); |
| 209 std::string name = "Omnibox.QueryTime." + base::IntToString(text.length()); | 209 std::string name = "Omnibox.QueryTime." + base::IntToString(text.length()); |
| 210 base::Histogram* counter = base::Histogram::FactoryGet( | 210 base::Histogram* counter = base::Histogram::FactoryGet( |
| 211 name, 1, 1000, 50, base::Histogram::kUmaTargetedHistogramFlag); | 211 name, 1, 1000, 50, base::Histogram::kUmaTargetedHistogramFlag); |
| 212 counter->Add(static_cast<int>((end_time - start_time).InMilliseconds())); | 212 counter->Add(static_cast<int>((end_time - start_time).InMilliseconds())); |
| 213 } | 213 } |
| 214 in_start_ = false; | 214 in_start_ = false; |
| 215 CheckIfDone(); | 215 CheckIfDone(); |
| 216 UpdateResult(true); | 216 // The second true forces saying the default match has changed. |
| 217 // This triggers the edit model to update things such as the inline |
| 218 // autocomplete state. In particular, if the user has typed a key |
| 219 // since the last notification, and we're now re-running |
| 220 // autocomplete, then we need to update the inline autocompletion |
| 221 // even if the current match is for the same URL as the last run's |
| 222 // default match. Likewise, the controller doesn't know what's |
| 223 // happened in the edit since the last time it ran autocomplete. |
| 224 // The user might have selected all the text and hit delete, then |
| 225 // typed a new character. The selection and delete won't send any |
| 226 // signals to the controller so it doesn't realize that anything was |
| 227 // cleared or changed. Even if the default match hasn't changed, we |
| 228 // need the edit model to update the display. |
| 229 UpdateResult(false, true); |
| 217 | 230 |
| 218 if (!done_) | 231 if (!done_) |
| 219 StartExpireTimer(); | 232 StartExpireTimer(); |
| 220 } | 233 } |
| 221 | 234 |
| 222 void AutocompleteController::Stop(bool clear_result) { | 235 void AutocompleteController::Stop(bool clear_result) { |
| 223 for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); | 236 for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); |
| 224 ++i) { | 237 ++i) { |
| 225 (*i)->Stop(clear_result); | 238 (*i)->Stop(clear_result); |
| 226 } | 239 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 256 DCHECK(match.deletable); | 269 DCHECK(match.deletable); |
| 257 match.provider->DeleteMatch(match); // This may synchronously call back to | 270 match.provider->DeleteMatch(match); // This may synchronously call back to |
| 258 // OnProviderUpdate(). | 271 // OnProviderUpdate(). |
| 259 // If DeleteMatch resulted in a callback to OnProviderUpdate and we're | 272 // If DeleteMatch resulted in a callback to OnProviderUpdate and we're |
| 260 // not done, we might attempt to redisplay the deleted match. Make sure | 273 // not done, we might attempt to redisplay the deleted match. Make sure |
| 261 // we aren't displaying it by removing any old entries. | 274 // we aren't displaying it by removing any old entries. |
| 262 ExpireCopiedEntries(); | 275 ExpireCopiedEntries(); |
| 263 } | 276 } |
| 264 | 277 |
| 265 void AutocompleteController::ExpireCopiedEntries() { | 278 void AutocompleteController::ExpireCopiedEntries() { |
| 266 // Clear out the results. This ensures no results from the previous result set | 279 // The first true makes UpdateResult() clear out the results and |
| 267 // are copied over. | 280 // regenerate them, thus ensuring that no results from the previous |
| 268 result_.Reset(); | 281 // result set remain. |
| 269 // We allow matches from the previous result set to starve out matches from | 282 // The second true says to pretend the default match changed (even |
| 270 // the new result set. This means in order to expire matches we have to query | 283 // if it did not). This may not be necessary but the code has been |
| 271 // the providers again. | 284 // like this for a long time and there's probably no great benefit in |
| 272 UpdateResult(false); | 285 // changing it. Classically we have erred on the side of notifying |
| 286 // too often because it hasn't had any major side effects. |
| 287 UpdateResult(true, true); |
| 273 } | 288 } |
| 274 | 289 |
| 275 void AutocompleteController::OnProviderUpdate(bool updated_matches) { | 290 void AutocompleteController::OnProviderUpdate(bool updated_matches) { |
| 276 if (in_zero_suggest_) { | 291 if (in_zero_suggest_) { |
| 277 // We got ZeroSuggest results before Start(). Show only those results, | 292 // We got ZeroSuggest results before Start(). Show only those results, |
| 278 // because results from other providers are stale. | 293 // because results from other providers are stale. |
| 279 result_.Reset(); | 294 result_.Reset(); |
| 280 result_.AppendMatches(zero_suggest_provider_->matches()); | 295 result_.AppendMatches(zero_suggest_provider_->matches()); |
| 281 result_.SortAndCull(input_, profile_); | 296 result_.SortAndCull(input_, profile_); |
| 282 NotifyChanged(true); | 297 NotifyChanged(true); |
| 283 } else { | 298 } else { |
| 284 CheckIfDone(); | 299 CheckIfDone(); |
| 285 // Multiple providers may provide synchronous results, so we only update the | 300 // Multiple providers may provide synchronous results, so we only update the |
| 286 // results if we're not in Start(). | 301 // results if we're not in Start(). |
| 287 if (!in_start_ && (updated_matches || done_)) | 302 if (!in_start_ && (updated_matches || done_)) |
| 288 UpdateResult(false); | 303 UpdateResult(false, false); |
| 289 } | 304 } |
| 290 } | 305 } |
| 291 | 306 |
| 292 void AutocompleteController::AddProvidersInfo( | 307 void AutocompleteController::AddProvidersInfo( |
| 293 ProvidersInfo* provider_info) const { | 308 ProvidersInfo* provider_info) const { |
| 294 provider_info->clear(); | 309 provider_info->clear(); |
| 295 for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); | 310 for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); |
| 296 ++i) { | 311 ++i) { |
| 297 // Add per-provider info, if any. | 312 // Add per-provider info, if any. |
| 298 (*i)->AddProviderInfo(provider_info); | 313 (*i)->AddProviderInfo(provider_info); |
| 299 | 314 |
| 300 // This is also a good place to put code to add info that you want to | 315 // This is also a good place to put code to add info that you want to |
| 301 // add for every provider. | 316 // add for every provider. |
| 302 } | 317 } |
| 303 } | 318 } |
| 304 | 319 |
| 305 void AutocompleteController::UpdateResult(bool is_synchronous_pass) { | 320 void AutocompleteController::UpdateResult( |
| 321 bool regenerate_result, |
| 322 bool force_notify_default_match_changed) { |
| 323 const bool last_default_was_valid = result_.default_match() != result_.end(); |
| 324 // The following two variables are only set and used if |
| 325 // |last_default_was_valid|. |
| 326 string16 last_default_fill_into_edit, last_default_associated_keyword; |
| 327 if (last_default_was_valid) { |
| 328 last_default_fill_into_edit = result_.default_match()->fill_into_edit; |
| 329 if (result_.default_match()->associated_keyword != NULL) |
| 330 last_default_associated_keyword = |
| 331 result_.default_match()->associated_keyword->keyword; |
| 332 } |
| 333 |
| 334 if (regenerate_result) |
| 335 result_.Reset(); |
| 336 |
| 306 AutocompleteResult last_result; | 337 AutocompleteResult last_result; |
| 307 last_result.Swap(&result_); | 338 last_result.Swap(&result_); |
| 308 | 339 |
| 309 for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); | 340 for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); |
| 310 ++i) | 341 ++i) |
| 311 result_.AppendMatches((*i)->matches()); | 342 result_.AppendMatches((*i)->matches()); |
| 312 | 343 |
| 313 // Sort the matches and trim to a small number of "best" matches. | 344 // Sort the matches and trim to a small number of "best" matches. |
| 314 result_.SortAndCull(input_, profile_); | 345 result_.SortAndCull(input_, profile_); |
| 315 | 346 |
| 316 // Need to validate before invoking CopyOldMatches as the old matches are not | 347 // Need to validate before invoking CopyOldMatches as the old matches are not |
| 317 // valid against the current input. | 348 // valid against the current input. |
| 318 #ifndef NDEBUG | 349 #ifndef NDEBUG |
| 319 result_.Validate(); | 350 result_.Validate(); |
| 320 #endif | 351 #endif |
| 321 | 352 |
| 322 if (!done_) { | 353 if (!done_) { |
| 323 // This conditional needs to match the conditional in Start that invokes | 354 // This conditional needs to match the conditional in Start that invokes |
| 324 // StartExpireTimer. | 355 // StartExpireTimer. |
| 325 result_.CopyOldMatches(input_, last_result, profile_); | 356 result_.CopyOldMatches(input_, last_result, profile_); |
| 326 } | 357 } |
| 327 | 358 |
| 328 UpdateKeywordDescriptions(&result_); | 359 UpdateKeywordDescriptions(&result_); |
| 329 UpdateAssociatedKeywords(&result_); | 360 UpdateAssociatedKeywords(&result_); |
| 330 UpdateAssistedQueryStats(&result_); | 361 UpdateAssistedQueryStats(&result_); |
| 331 | 362 |
| 332 bool notify_default_match = is_synchronous_pass; | 363 const bool default_is_valid = result_.default_match() != result_.end(); |
| 333 if (!is_synchronous_pass) { | 364 string16 default_associated_keyword; |
| 334 const bool last_default_was_valid = | 365 if (default_is_valid && |
| 335 last_result.default_match() != last_result.end(); | 366 (result_.default_match()->associated_keyword != NULL)) { |
| 336 const bool default_is_valid = result_.default_match() != result_.end(); | 367 default_associated_keyword = |
| 337 // We've gotten async results. Send notification that the default match | 368 result_.default_match()->associated_keyword->keyword; |
| 338 // updated if fill_into_edit differs or associated_keyword differ. (The | |
| 339 // latter can change if we've just started Chrome and the keyword database | |
| 340 // finishes loading while processing this request.) We don't check the URL | |
| 341 // as that may change for the default match even though the fill into edit | |
| 342 // hasn't changed (see SearchProvider for one case of this). | |
| 343 notify_default_match = | |
| 344 (last_default_was_valid != default_is_valid) || | |
| 345 (default_is_valid && | |
| 346 ((result_.default_match()->fill_into_edit != | |
| 347 last_result.default_match()->fill_into_edit) || | |
| 348 (result_.default_match()->associated_keyword.get() != | |
| 349 last_result.default_match()->associated_keyword.get()))); | |
| 350 } | 369 } |
| 370 // We've gotten async results. Send notification that the default match |
| 371 // updated if fill_into_edit differs or associated_keyword differ. (The |
| 372 // latter can change if we've just started Chrome and the keyword database |
| 373 // finishes loading while processing this request.) We don't check the URL |
| 374 // as that may change for the default match even though the fill into edit |
| 375 // hasn't changed (see SearchProvider for one case of this). |
| 376 const bool notify_default_match = |
| 377 (last_default_was_valid != default_is_valid) || |
| 378 (last_default_was_valid && |
| 379 ((result_.default_match()->fill_into_edit != |
| 380 last_default_fill_into_edit) || |
| 381 (default_associated_keyword != last_default_associated_keyword))); |
| 382 if (notify_default_match) |
| 383 last_time_default_match_changed_ = base::TimeTicks::Now(); |
| 351 | 384 |
| 352 NotifyChanged(notify_default_match); | 385 NotifyChanged(force_notify_default_match_changed || notify_default_match); |
| 353 } | 386 } |
| 354 | 387 |
| 355 void AutocompleteController::UpdateAssociatedKeywords( | 388 void AutocompleteController::UpdateAssociatedKeywords( |
| 356 AutocompleteResult* result) { | 389 AutocompleteResult* result) { |
| 357 if (!keyword_provider_) | 390 if (!keyword_provider_) |
| 358 return; | 391 return; |
| 359 | 392 |
| 360 std::set<string16> keywords; | 393 std::set<string16> keywords; |
| 361 for (ACMatches::iterator match(result->begin()); match != result->end(); | 394 for (ACMatches::iterator match(result->begin()); match != result->end(); |
| 362 ++match) { | 395 ++match) { |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 471 } | 504 } |
| 472 done_ = true; | 505 done_ = true; |
| 473 } | 506 } |
| 474 | 507 |
| 475 void AutocompleteController::StartExpireTimer() { | 508 void AutocompleteController::StartExpireTimer() { |
| 476 if (result_.HasCopiedMatches()) | 509 if (result_.HasCopiedMatches()) |
| 477 expire_timer_.Start(FROM_HERE, | 510 expire_timer_.Start(FROM_HERE, |
| 478 base::TimeDelta::FromMilliseconds(kExpireTimeMS), | 511 base::TimeDelta::FromMilliseconds(kExpireTimeMS), |
| 479 this, &AutocompleteController::ExpireCopiedEntries); | 512 this, &AutocompleteController::ExpireCopiedEntries); |
| 480 } | 513 } |
| OLD | NEW |