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