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 |