Chromium Code Reviews| 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/format_macros.h" | 10 #include "base/format_macros.h" |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 203 search_provider_ = new SearchProvider(this, profile); | 203 search_provider_ = new SearchProvider(this, profile); |
| 204 providers_.push_back(search_provider_); | 204 providers_.push_back(search_provider_); |
| 205 } | 205 } |
| 206 if (provider_types & AutocompleteProvider::TYPE_SHORTCUTS) | 206 if (provider_types & AutocompleteProvider::TYPE_SHORTCUTS) |
| 207 providers_.push_back(new ShortcutsProvider(this, profile)); | 207 providers_.push_back(new ShortcutsProvider(this, profile)); |
| 208 if (provider_types & AutocompleteProvider::TYPE_ZERO_SUGGEST) { | 208 if (provider_types & AutocompleteProvider::TYPE_ZERO_SUGGEST) { |
| 209 zero_suggest_provider_ = ZeroSuggestProvider::Create(this, profile); | 209 zero_suggest_provider_ = ZeroSuggestProvider::Create(this, profile); |
| 210 if (zero_suggest_provider_) | 210 if (zero_suggest_provider_) |
| 211 providers_.push_back(zero_suggest_provider_); | 211 providers_.push_back(zero_suggest_provider_); |
| 212 } | 212 } |
| 213 | |
| 214 for (ACProviders::iterator i(providers_.begin()); i != providers_.end(); ++i) | |
| 215 (*i)->AddRef(); | |
| 216 } | 213 } |
| 217 | 214 |
| 218 AutocompleteController::~AutocompleteController() { | 215 AutocompleteController::~AutocompleteController() { |
| 219 // The providers may have tasks outstanding that hold refs to them. We need | 216 // The providers may have tasks outstanding that hold refs to them. We need |
| 220 // to ensure they won't call us back if they outlive us. (Practically, | 217 // to ensure they won't call us back if they outlive us. (Practically, |
| 221 // calling Stop() should also cancel those tasks and make it so that we hold | 218 // calling Stop() should also cancel those tasks and make it so that we hold |
| 222 // the only refs.) We also don't want to bother notifying anyone of our | 219 // the only refs.) We also don't want to bother notifying anyone of our |
| 223 // result changes here, because the notification observer is in the midst of | 220 // result changes here, because the notification observer is in the midst of |
| 224 // shutdown too, so we don't ask Stop() to clear |result_| (and notify). | 221 // shutdown too, so we don't ask Stop() to clear |result_| (and notify). |
| 225 result_.Reset(); // Not really necessary. | 222 result_.Reset(); // Not really necessary. |
| 226 Stop(false); | 223 Stop(false); |
| 227 | |
| 228 for (ACProviders::iterator i(providers_.begin()); i != providers_.end(); ++i) | |
| 229 (*i)->Release(); | |
| 230 | |
| 231 providers_.clear(); // Not really necessary. | 224 providers_.clear(); // Not really necessary. |
|
Peter Kasting
2014/07/09 01:07:32
Go ahead and remove this line.
hashimoto
2014/07/09 01:57:29
Done.
| |
| 232 } | 225 } |
| 233 | 226 |
| 234 void AutocompleteController::Start(const AutocompleteInput& input) { | 227 void AutocompleteController::Start(const AutocompleteInput& input) { |
| 235 const base::string16 old_input_text(input_.text()); | 228 const base::string16 old_input_text(input_.text()); |
| 236 const bool old_want_asynchronous_matches = input_.want_asynchronous_matches(); | 229 const bool old_want_asynchronous_matches = input_.want_asynchronous_matches(); |
| 237 input_ = input; | 230 input_ = input; |
| 238 | 231 |
| 239 // See if we can avoid rerunning autocomplete when the query hasn't changed | 232 // See if we can avoid rerunning autocomplete when the query hasn't changed |
| 240 // much. When the user presses or releases the ctrl key, the desired_tld | 233 // much. When the user presses or releases the ctrl key, the desired_tld |
| 241 // changes, and when the user finishes an IME composition, inline autocomplete | 234 // changes, and when the user finishes an IME composition, inline autocomplete |
| 242 // may no longer be prevented. In both these cases the text itself hasn't | 235 // may no longer be prevented. In both these cases the text itself hasn't |
| 243 // changed since the last query, and some providers can do much less work (and | 236 // changed since the last query, and some providers can do much less work (and |
| 244 // get matches back more quickly). Taking advantage of this reduces flicker. | 237 // get matches back more quickly). Taking advantage of this reduces flicker. |
| 245 // | 238 // |
| 246 // NOTE: This comes after constructing |input_| above since that construction | 239 // NOTE: This comes after constructing |input_| above since that construction |
| 247 // can change the text string (e.g. by stripping off a leading '?'). | 240 // can change the text string (e.g. by stripping off a leading '?'). |
| 248 const bool minimal_changes = (input_.text() == old_input_text) && | 241 const bool minimal_changes = (input_.text() == old_input_text) && |
| 249 (input_.want_asynchronous_matches() == old_want_asynchronous_matches); | 242 (input_.want_asynchronous_matches() == old_want_asynchronous_matches); |
| 250 | 243 |
| 251 expire_timer_.Stop(); | 244 expire_timer_.Stop(); |
| 252 stop_timer_.Stop(); | 245 stop_timer_.Stop(); |
| 253 | 246 |
| 254 // Start the new query. | 247 // Start the new query. |
| 255 in_start_ = true; | 248 in_start_ = true; |
| 256 base::TimeTicks start_time = base::TimeTicks::Now(); | 249 base::TimeTicks start_time = base::TimeTicks::Now(); |
| 257 for (ACProviders::iterator i(providers_.begin()); i != providers_.end(); | 250 for (Providers::iterator i(providers_.begin()); i != providers_.end(); ++i) { |
| 258 ++i) { | |
| 259 // TODO(mpearson): Remove timing code once bugs 178705 / 237703 / 168933 | 251 // TODO(mpearson): Remove timing code once bugs 178705 / 237703 / 168933 |
| 260 // are resolved. | 252 // are resolved. |
| 261 base::TimeTicks provider_start_time = base::TimeTicks::Now(); | 253 base::TimeTicks provider_start_time = base::TimeTicks::Now(); |
| 262 | 254 |
| 263 // Call Start() on ZeroSuggestProvider with an INVALID AutocompleteInput | 255 // Call Start() on ZeroSuggestProvider with an INVALID AutocompleteInput |
| 264 // to clear out zero-suggest |matches_|. | 256 // to clear out zero-suggest |matches_|. |
| 265 if (*i == zero_suggest_provider_) | 257 if (*i == zero_suggest_provider_) |
| 266 (*i)->Start(AutocompleteInput(), minimal_changes); | 258 (*i)->Start(AutocompleteInput(), minimal_changes); |
| 267 else | 259 else |
| 268 (*i)->Start(input_, minimal_changes); | 260 (*i)->Start(input_, minimal_changes); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 301 // need the edit model to update the display. | 293 // need the edit model to update the display. |
| 302 UpdateResult(false, true); | 294 UpdateResult(false, true); |
| 303 | 295 |
| 304 if (!done_) { | 296 if (!done_) { |
| 305 StartExpireTimer(); | 297 StartExpireTimer(); |
| 306 StartStopTimer(); | 298 StartStopTimer(); |
| 307 } | 299 } |
| 308 } | 300 } |
| 309 | 301 |
| 310 void AutocompleteController::Stop(bool clear_result) { | 302 void AutocompleteController::Stop(bool clear_result) { |
| 311 for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); | 303 for (Providers::const_iterator i(providers_.begin()); i != providers_.end(); |
| 312 ++i) { | 304 ++i) { |
| 313 (*i)->Stop(clear_result); | 305 (*i)->Stop(clear_result); |
| 314 } | 306 } |
| 315 | 307 |
| 316 expire_timer_.Stop(); | 308 expire_timer_.Stop(); |
| 317 stop_timer_.Stop(); | 309 stop_timer_.Stop(); |
| 318 done_ = true; | 310 done_ = true; |
| 319 if (clear_result && !result_.empty()) { | 311 if (clear_result && !result_.empty()) { |
| 320 result_.Reset(); | 312 result_.Reset(); |
| 321 // NOTE: We pass in false since we're trying to only clear the popup, not | 313 // NOTE: We pass in false since we're trying to only clear the popup, not |
| 322 // touch the edit... this is all a mess and should be cleaned up :( | 314 // touch the edit... this is all a mess and should be cleaned up :( |
| 323 NotifyChanged(false); | 315 NotifyChanged(false); |
| 324 } | 316 } |
| 325 } | 317 } |
| 326 | 318 |
| 327 void AutocompleteController::StartZeroSuggest(const AutocompleteInput& input) { | 319 void AutocompleteController::StartZeroSuggest(const AutocompleteInput& input) { |
| 328 if (zero_suggest_provider_ == NULL) | 320 if (zero_suggest_provider_ == NULL) |
| 329 return; | 321 return; |
| 330 | 322 |
| 331 DCHECK(!in_start_); // We should not be already running a query. | 323 DCHECK(!in_start_); // We should not be already running a query. |
| 332 | 324 |
| 333 // Call Start() on all prefix-based providers with an INVALID | 325 // Call Start() on all prefix-based providers with an INVALID |
| 334 // AutocompleteInput to clear out cached |matches_|, which ensures that | 326 // AutocompleteInput to clear out cached |matches_|, which ensures that |
| 335 // they aren't used with zero suggest. | 327 // they aren't used with zero suggest. |
| 336 for (ACProviders::iterator i(providers_.begin()); i != providers_.end(); | 328 for (Providers::iterator i(providers_.begin()); i != providers_.end(); ++i) { |
| 337 ++i) { | |
| 338 if (*i == zero_suggest_provider_) | 329 if (*i == zero_suggest_provider_) |
| 339 (*i)->Start(input, false); | 330 (*i)->Start(input, false); |
| 340 else | 331 else |
| 341 (*i)->Start(AutocompleteInput(), false); | 332 (*i)->Start(AutocompleteInput(), false); |
| 342 } | 333 } |
| 343 | 334 |
| 344 if (!zero_suggest_provider_->matches().empty()) | 335 if (!zero_suggest_provider_->matches().empty()) |
| 345 UpdateResult(false, false); | 336 UpdateResult(false, false); |
| 346 } | 337 } |
| 347 | 338 |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 376 CheckIfDone(); | 367 CheckIfDone(); |
| 377 // Multiple providers may provide synchronous results, so we only update the | 368 // Multiple providers may provide synchronous results, so we only update the |
| 378 // results if we're not in Start(). | 369 // results if we're not in Start(). |
| 379 if (!in_start_ && (updated_matches || done_)) | 370 if (!in_start_ && (updated_matches || done_)) |
| 380 UpdateResult(false, false); | 371 UpdateResult(false, false); |
| 381 } | 372 } |
| 382 | 373 |
| 383 void AutocompleteController::AddProvidersInfo( | 374 void AutocompleteController::AddProvidersInfo( |
| 384 ProvidersInfo* provider_info) const { | 375 ProvidersInfo* provider_info) const { |
| 385 provider_info->clear(); | 376 provider_info->clear(); |
| 386 for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); | 377 for (Providers::const_iterator i(providers_.begin()); i != providers_.end(); |
| 387 ++i) { | 378 ++i) { |
| 388 // Add per-provider info, if any. | 379 // Add per-provider info, if any. |
| 389 (*i)->AddProviderInfo(provider_info); | 380 (*i)->AddProviderInfo(provider_info); |
| 390 | 381 |
| 391 // This is also a good place to put code to add info that you want to | 382 // This is also a good place to put code to add info that you want to |
| 392 // add for every provider. | 383 // add for every provider. |
| 393 } | 384 } |
| 394 } | 385 } |
| 395 | 386 |
| 396 void AutocompleteController::ResetSession() { | 387 void AutocompleteController::ResetSession() { |
| 397 for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); | 388 for (Providers::const_iterator i(providers_.begin()); i != providers_.end(); |
| 398 ++i) | 389 ++i) |
| 399 (*i)->ResetSession(); | 390 (*i)->ResetSession(); |
| 400 } | 391 } |
| 401 | 392 |
| 402 void AutocompleteController::UpdateMatchDestinationURL( | 393 void AutocompleteController::UpdateMatchDestinationURL( |
| 403 base::TimeDelta query_formulation_time, | 394 base::TimeDelta query_formulation_time, |
| 404 AutocompleteMatch* match) const { | 395 AutocompleteMatch* match) const { |
| 405 TemplateURL* template_url = match->GetTemplateURL( | 396 TemplateURL* template_url = match->GetTemplateURL( |
| 406 template_url_service_, false); | 397 template_url_service_, false); |
| 407 if (!template_url || !match->search_terms_args.get() || | 398 if (!template_url || !match->search_terms_args.get() || |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 439 last_default_associated_keyword = | 430 last_default_associated_keyword = |
| 440 result_.default_match()->associated_keyword->keyword; | 431 result_.default_match()->associated_keyword->keyword; |
| 441 } | 432 } |
| 442 | 433 |
| 443 if (regenerate_result) | 434 if (regenerate_result) |
| 444 result_.Reset(); | 435 result_.Reset(); |
| 445 | 436 |
| 446 AutocompleteResult last_result; | 437 AutocompleteResult last_result; |
| 447 last_result.Swap(&result_); | 438 last_result.Swap(&result_); |
| 448 | 439 |
| 449 for (ACProviders::const_iterator i(providers_.begin()); | 440 for (Providers::const_iterator i(providers_.begin()); |
| 450 i != providers_.end(); ++i) | 441 i != providers_.end(); ++i) |
| 451 result_.AppendMatches((*i)->matches()); | 442 result_.AppendMatches((*i)->matches()); |
| 452 | 443 |
| 453 // Sort the matches and trim to a small number of "best" matches. | 444 // Sort the matches and trim to a small number of "best" matches. |
| 454 result_.SortAndCull(input_, template_url_service_); | 445 result_.SortAndCull(input_, template_url_service_); |
| 455 | 446 |
| 456 // Need to validate before invoking CopyOldMatches as the old matches are not | 447 // Need to validate before invoking CopyOldMatches as the old matches are not |
| 457 // valid against the current input. | 448 // valid against the current input. |
| 458 #ifndef NDEBUG | 449 #ifndef NDEBUG |
| 459 result_.Validate(); | 450 result_.Validate(); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 619 delegate_->OnResultChanged(notify_default_match); | 610 delegate_->OnResultChanged(notify_default_match); |
| 620 if (done_) { | 611 if (done_) { |
| 621 content::NotificationService::current()->Notify( | 612 content::NotificationService::current()->Notify( |
| 622 chrome::NOTIFICATION_AUTOCOMPLETE_CONTROLLER_RESULT_READY, | 613 chrome::NOTIFICATION_AUTOCOMPLETE_CONTROLLER_RESULT_READY, |
| 623 content::Source<AutocompleteController>(this), | 614 content::Source<AutocompleteController>(this), |
| 624 content::NotificationService::NoDetails()); | 615 content::NotificationService::NoDetails()); |
| 625 } | 616 } |
| 626 } | 617 } |
| 627 | 618 |
| 628 void AutocompleteController::CheckIfDone() { | 619 void AutocompleteController::CheckIfDone() { |
| 629 for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); | 620 for (Providers::const_iterator i(providers_.begin()); i != providers_.end(); |
| 630 ++i) { | 621 ++i) { |
| 631 if (!(*i)->done()) { | 622 if (!(*i)->done()) { |
| 632 done_ = false; | 623 done_ = false; |
| 633 return; | 624 return; |
| 634 } | 625 } |
| 635 } | 626 } |
| 636 done_ = true; | 627 done_ = true; |
| 637 } | 628 } |
| 638 | 629 |
| 639 void AutocompleteController::StartExpireTimer() { | 630 void AutocompleteController::StartExpireTimer() { |
| 640 // Amount of time (in ms) between when the user stops typing and | 631 // Amount of time (in ms) between when the user stops typing and |
| 641 // when we remove any copied entries. We do this from the time the | 632 // when we remove any copied entries. We do this from the time the |
| 642 // user stopped typing as some providers (such as SearchProvider) | 633 // user stopped typing as some providers (such as SearchProvider) |
| 643 // wait for the user to stop typing before they initiate a query. | 634 // wait for the user to stop typing before they initiate a query. |
| 644 const int kExpireTimeMS = 500; | 635 const int kExpireTimeMS = 500; |
| 645 | 636 |
| 646 if (result_.HasCopiedMatches()) | 637 if (result_.HasCopiedMatches()) |
| 647 expire_timer_.Start(FROM_HERE, | 638 expire_timer_.Start(FROM_HERE, |
| 648 base::TimeDelta::FromMilliseconds(kExpireTimeMS), | 639 base::TimeDelta::FromMilliseconds(kExpireTimeMS), |
| 649 this, &AutocompleteController::ExpireCopiedEntries); | 640 this, &AutocompleteController::ExpireCopiedEntries); |
| 650 } | 641 } |
| 651 | 642 |
| 652 void AutocompleteController::StartStopTimer() { | 643 void AutocompleteController::StartStopTimer() { |
| 653 stop_timer_.Start(FROM_HERE, | 644 stop_timer_.Start(FROM_HERE, |
| 654 stop_timer_duration_, | 645 stop_timer_duration_, |
| 655 base::Bind(&AutocompleteController::Stop, | 646 base::Bind(&AutocompleteController::Stop, |
| 656 base::Unretained(this), | 647 base::Unretained(this), |
| 657 false)); | 648 false)); |
| 658 } | 649 } |
| OLD | NEW |