OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 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/ui/search/instant_controller.h" | 5 #include "chrome/browser/ui/search/instant_controller.h" |
6 | 6 |
7 #include <iterator> | 7 #include <iterator> |
8 | 8 |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "base/prefs/pref_service.h" | 10 #include "base/prefs/pref_service.h" |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 } | 426 } |
427 } else if (full_text.empty()) { | 427 } else if (full_text.empty()) { |
428 // The user is typing, and backspaced away all omnibox text. Clear | 428 // The user is typing, and backspaced away all omnibox text. Clear |
429 // |last_omnibox_text_| so that we don't attempt to set suggestions. | 429 // |last_omnibox_text_| so that we don't attempt to set suggestions. |
430 last_omnibox_text_.clear(); | 430 last_omnibox_text_.clear(); |
431 last_user_text_.clear(); | 431 last_user_text_.clear(); |
432 last_suggestion_ = InstantSuggestion(); | 432 last_suggestion_ = InstantSuggestion(); |
433 if (UseTabForSuggestions()) { | 433 if (UseTabForSuggestions()) { |
434 // On a search results page, tell it to clear old results. | 434 // On a search results page, tell it to clear old results. |
435 instant_tab_->Update(string16(), 0, 0, true); | 435 instant_tab_->Update(string16(), 0, 0, true); |
436 } else if (search_mode_.is_origin_ntp()) { | 436 } else if (overlay_ && search_mode_.is_origin_ntp()) { |
437 // On the NTP, tell the overlay to clear old results. Don't hide the | 437 // On the NTP, tell the overlay to clear old results. Don't hide the |
438 // overlay so it can show a blank page or logo if it wants. | 438 // overlay so it can show a blank page or logo if it wants. |
439 overlay_->Update(string16(), 0, 0, true); | 439 overlay_->Update(string16(), 0, 0, true); |
440 } else { | 440 } else { |
441 HideOverlay(); | 441 HideOverlay(); |
442 } | 442 } |
443 } else { | 443 } else { |
444 // The user switched to a tab with partial text already in the omnibox. | 444 // The user switched to a tab with partial text already in the omnibox. |
445 HideOverlay(); | 445 HideOverlay(); |
446 | 446 |
447 // The new tab may or may not be a search results page; we don't know | 447 // The new tab may or may not be a search results page; we don't know |
448 // since SearchModeChanged() hasn't been called yet. If it later turns | 448 // since SearchModeChanged() hasn't been called yet. If it later turns |
449 // out to be, we should store |full_text| now, so that if the user hits | 449 // out to be, we should store |full_text| now, so that if the user hits |
450 // Enter, we'll send the correct query to instant_tab_->Submit(). If the | 450 // Enter, we'll send the correct query to instant_tab_->Submit(). If the |
451 // partial text is not a query (|last_match_was_search_| is false), we | 451 // partial text is not a query (|last_match_was_search_| is false), we |
452 // won't Submit(), so no need to worry about that. | 452 // won't Submit(), so no need to worry about that. |
453 last_user_text_ = user_text; | 453 last_user_text_ = user_text; |
454 last_suggestion_ = InstantSuggestion(); | 454 last_suggestion_ = InstantSuggestion(); |
455 } | 455 } |
456 return false; | 456 return false; |
457 } else if (full_text.empty()) { | 457 } else if (full_text.empty()) { |
458 // The user typed a solitary "?". Same as the backspace case above. | 458 // The user typed a solitary "?". Same as the backspace case above. |
459 last_omnibox_text_.clear(); | 459 last_omnibox_text_.clear(); |
460 last_user_text_.clear(); | 460 last_user_text_.clear(); |
461 last_suggestion_ = InstantSuggestion(); | 461 last_suggestion_ = InstantSuggestion(); |
462 if (UseTabForSuggestions()) | 462 if (UseTabForSuggestions()) |
463 instant_tab_->Update(string16(), 0, 0, true); | 463 instant_tab_->Update(string16(), 0, 0, true); |
464 else if (search_mode_.is_origin_ntp()) | 464 else if (overlay_ && search_mode_.is_origin_ntp()) |
465 overlay_->Update(string16(), 0, 0, true); | 465 overlay_->Update(string16(), 0, 0, true); |
466 else | 466 else |
467 HideOverlay(); | 467 HideOverlay(); |
468 return false; | 468 return false; |
469 } | 469 } |
470 } else if (!omnibox_popup_is_open || full_text.empty()) { | 470 } else if (!omnibox_popup_is_open || full_text.empty()) { |
471 // In the non-extended case, hide the overlay as long as the user isn't | 471 // In the non-extended case, hide the overlay as long as the user isn't |
472 // actively typing a non-empty query. | 472 // actively typing a non-empty query. |
473 HideOverlay(); | 473 HideOverlay(); |
474 return false; | 474 return false; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 last_transition_type_ = match.transition; | 510 last_transition_type_ = match.transition; |
511 url_for_history_ = match.destination_url; | 511 url_for_history_ = match.destination_url; |
512 | 512 |
513 // Allow search suggestions. In extended mode, SearchModeChanged() will set | 513 // Allow search suggestions. In extended mode, SearchModeChanged() will set |
514 // this, but it's not called in non-extended mode, so fake it. | 514 // this, but it's not called in non-extended mode, so fake it. |
515 if (!extended_enabled()) | 515 if (!extended_enabled()) |
516 search_mode_.mode = SearchMode::MODE_SEARCH_SUGGESTIONS; | 516 search_mode_.mode = SearchMode::MODE_SEARCH_SUGGESTIONS; |
517 | 517 |
518 if (UseTabForSuggestions()) { | 518 if (UseTabForSuggestions()) { |
519 instant_tab_->Update(user_text, selection_start, selection_end, verbatim); | 519 instant_tab_->Update(user_text, selection_start, selection_end, verbatim); |
520 } else { | 520 } else if (overlay_) { |
521 allow_overlay_to_show_search_suggestions_ = true; | 521 allow_overlay_to_show_search_suggestions_ = true; |
522 | 522 |
523 overlay_->Update(extended_enabled() ? user_text : full_text, | 523 overlay_->Update(extended_enabled() ? user_text : full_text, |
524 selection_start, selection_end, verbatim); | 524 selection_start, selection_end, verbatim); |
525 } | 525 } |
526 | 526 |
527 content::NotificationService::current()->Notify( | 527 content::NotificationService::current()->Notify( |
528 chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED, | 528 chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED, |
529 content::Source<InstantController>(this), | 529 content::Source<InstantController>(this), |
530 content::NotificationService::NoDetails()); | 530 content::NotificationService::NoDetails()); |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 results.push_back(result); | 663 results.push_back(result); |
664 } | 664 } |
665 } | 665 } |
666 } | 666 } |
667 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( | 667 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( |
668 "HandleAutocompleteResults: total_results=%d", | 668 "HandleAutocompleteResults: total_results=%d", |
669 static_cast<int>(results.size()))); | 669 static_cast<int>(results.size()))); |
670 | 670 |
671 if (UseTabForSuggestions()) | 671 if (UseTabForSuggestions()) |
672 instant_tab_->SendAutocompleteResults(results); | 672 instant_tab_->SendAutocompleteResults(results); |
673 else | 673 else if (overlay_) |
674 overlay_->SendAutocompleteResults(results); | 674 overlay_->SendAutocompleteResults(results); |
675 | 675 |
676 content::NotificationService::current()->Notify( | 676 content::NotificationService::current()->Notify( |
677 chrome::NOTIFICATION_INSTANT_SENT_AUTOCOMPLETE_RESULTS, | 677 chrome::NOTIFICATION_INSTANT_SENT_AUTOCOMPLETE_RESULTS, |
678 content::Source<InstantController>(this), | 678 content::Source<InstantController>(this), |
679 content::NotificationService::NoDetails()); | 679 content::NotificationService::NoDetails()); |
680 } | 680 } |
681 | 681 |
682 void InstantController::OnDefaultSearchProviderChanged() { | 682 void InstantController::OnDefaultSearchProviderChanged() { |
683 if (ntp_ && extended_enabled()) { | 683 if (ntp_ && extended_enabled()) { |
(...skipping 15 matching lines...) Expand all Loading... |
699 | 699 |
700 bool InstantController::OnUpOrDownKeyPressed(int count) { | 700 bool InstantController::OnUpOrDownKeyPressed(int count) { |
701 if (!extended_enabled()) | 701 if (!extended_enabled()) |
702 return false; | 702 return false; |
703 | 703 |
704 if (!UseTabForSuggestions() && !overlay_) | 704 if (!UseTabForSuggestions() && !overlay_) |
705 return false; | 705 return false; |
706 | 706 |
707 if (UseTabForSuggestions()) | 707 if (UseTabForSuggestions()) |
708 instant_tab_->UpOrDownKeyPressed(count); | 708 instant_tab_->UpOrDownKeyPressed(count); |
709 else | 709 else if (overlay_) |
710 overlay_->UpOrDownKeyPressed(count); | 710 overlay_->UpOrDownKeyPressed(count); |
711 | 711 |
712 return true; | 712 return true; |
713 } | 713 } |
714 | 714 |
715 void InstantController::OnCancel(const AutocompleteMatch& match, | 715 void InstantController::OnCancel(const AutocompleteMatch& match, |
716 const string16& user_text, | 716 const string16& user_text, |
717 const string16& full_text) { | 717 const string16& full_text) { |
718 if (!extended_enabled()) | 718 if (!extended_enabled()) |
719 return; | 719 return; |
720 | 720 |
721 if (!UseTabForSuggestions() && !overlay_) | 721 if (!UseTabForSuggestions() && !overlay_) |
722 return; | 722 return; |
723 | 723 |
724 // We manually reset the state here since the JS is not expected to do it. | 724 // We manually reset the state here since the JS is not expected to do it. |
725 // TODO(sreeram): Handle the case where user_text is now a URL | 725 // TODO(sreeram): Handle the case where user_text is now a URL |
726 last_match_was_search_ = AutocompleteMatch::IsSearchType(match.type) && | 726 last_match_was_search_ = AutocompleteMatch::IsSearchType(match.type) && |
727 !full_text.empty(); | 727 !full_text.empty(); |
728 last_omnibox_text_ = full_text; | 728 last_omnibox_text_ = full_text; |
729 last_user_text_ = user_text; | 729 last_user_text_ = user_text; |
730 last_suggestion_ = InstantSuggestion(); | 730 last_suggestion_ = InstantSuggestion(); |
731 | 731 |
732 // Say |full_text| is "amazon.com" and |user_text| is "ama". This means the | 732 // Say |full_text| is "amazon.com" and |user_text| is "ama". This means the |
733 // inline autocompletion is "zon.com"; so the selection should span from | 733 // inline autocompletion is "zon.com"; so the selection should span from |
734 // user_text.size() to full_text.size(). The selection bounds are inverted | 734 // user_text.size() to full_text.size(). The selection bounds are inverted |
735 // because the caret is at the end of |user_text|, not |full_text|. | 735 // because the caret is at the end of |user_text|, not |full_text|. |
736 if (UseTabForSuggestions()) { | 736 if (UseTabForSuggestions()) { |
737 instant_tab_->CancelSelection(user_text, full_text.size(), user_text.size(), | 737 instant_tab_->CancelSelection(user_text, full_text.size(), user_text.size(), |
738 last_verbatim_); | 738 last_verbatim_); |
739 } else { | 739 } else if (overlay_) { |
740 overlay_->CancelSelection(user_text, full_text.size(), user_text.size(), | 740 overlay_->CancelSelection(user_text, full_text.size(), user_text.size(), |
741 last_verbatim_); | 741 last_verbatim_); |
742 } | 742 } |
743 } | 743 } |
744 | 744 |
745 void InstantController::OmniboxNavigateToURL() { | 745 void InstantController::OmniboxNavigateToURL() { |
746 RecordNavigationHistogram(UsingLocalPage(), false, extended_enabled()); | 746 RecordNavigationHistogram(UsingLocalPage(), false, extended_enabled()); |
747 if (!extended_enabled()) | 747 if (!extended_enabled()) |
748 return; | 748 return; |
749 if (UseTabForSuggestions()) | 749 if (UseTabForSuggestions()) |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
842 last_suggestion_.behavior == INSTANT_COMPLETE_NEVER)) { | 842 last_suggestion_.behavior == INSTANT_COMPLETE_NEVER)) { |
843 last_suggestion_.text.clear(); | 843 last_suggestion_.text.clear(); |
844 instant_tab_->Submit(last_omnibox_text_); | 844 instant_tab_->Submit(last_omnibox_text_); |
845 instant_tab_->contents()->GetView()->Focus(); | 845 instant_tab_->contents()->GetView()->Focus(); |
846 EnsureSearchTermsAreSet(instant_tab_->contents(), last_omnibox_text_); | 846 EnsureSearchTermsAreSet(instant_tab_->contents(), last_omnibox_text_); |
847 return true; | 847 return true; |
848 } | 848 } |
849 return false; | 849 return false; |
850 } | 850 } |
851 | 851 |
| 852 if (!overlay_) |
| 853 return false; |
| 854 |
852 // If the overlay is not showing at all, don't commit it. | 855 // If the overlay is not showing at all, don't commit it. |
853 if (!model_.mode().is_search_suggestions()) | 856 if (!model_.mode().is_search_suggestions()) |
854 return false; | 857 return false; |
855 | 858 |
856 // If the overlay is showing at full height (with results), commit it. | 859 // If the overlay is showing at full height (with results), commit it. |
857 // If it's showing at parial height, commit if it's navigating. | 860 // If it's showing at parial height, commit if it's navigating. |
858 if (!IsOverlayingSearchResults() && type != INSTANT_COMMIT_NAVIGATED) | 861 if (!IsOverlayingSearchResults() && type != INSTANT_COMMIT_NAVIGATED) |
859 return false; | 862 return false; |
860 | 863 |
861 // There may re-entrance here, from the call to browser_->CommitInstant below, | 864 // There may re-entrance here, from the call to browser_->CommitInstant below, |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1115 return; | 1118 return; |
1116 | 1119 |
1117 // If the overlay is showing or the omnibox has focus, don't refresh the | 1120 // If the overlay is showing or the omnibox has focus, don't refresh the |
1118 // overlay. It will get refreshed the next time the overlay is hidden or the | 1121 // overlay. It will get refreshed the next time the overlay is hidden or the |
1119 // omnibox loses focus. | 1122 // omnibox loses focus. |
1120 if (omnibox_focus_state_ == OMNIBOX_FOCUS_NONE && model_.mode().is_default()) | 1123 if (omnibox_focus_state_ == OMNIBOX_FOCUS_NONE && model_.mode().is_default()) |
1121 ResetOverlay(GetInstantURL()); | 1124 ResetOverlay(GetInstantURL()); |
1122 } | 1125 } |
1123 | 1126 |
1124 void InstantController::OverlayLoadCompletedMainFrame() { | 1127 void InstantController::OverlayLoadCompletedMainFrame() { |
1125 if (overlay_->supports_instant()) | 1128 if (!overlay_ || overlay_->supports_instant()) |
1126 return; | 1129 return; |
1127 InstantService* instant_service = | 1130 InstantService* instant_service = |
1128 InstantServiceFactory::GetForProfile(browser_->profile()); | 1131 InstantServiceFactory::GetForProfile(browser_->profile()); |
1129 content::WebContents* contents = overlay_->contents(); | 1132 content::WebContents* contents = overlay_->contents(); |
1130 DCHECK(contents); | 1133 DCHECK(contents); |
1131 if (instant_service->IsInstantProcess( | 1134 if (instant_service->IsInstantProcess( |
1132 contents->GetRenderProcessHost()->GetID())) { | 1135 contents->GetRenderProcessHost()->GetID())) { |
1133 return; | 1136 return; |
1134 } | 1137 } |
1135 InstantSupportDetermined(contents, false); | 1138 InstantSupportDetermined(contents, false); |
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1620 return false; | 1623 return false; |
1621 | 1624 |
1622 // The preloaded NTP does not support instant yet. If we're not in startup, | 1625 // The preloaded NTP does not support instant yet. If we're not in startup, |
1623 // always fall back to the local NTP. If we are in startup, use the local NTP | 1626 // always fall back to the local NTP. If we are in startup, use the local NTP |
1624 // (unless the finch flag to use the remote NTP is set). | 1627 // (unless the finch flag to use the remote NTP is set). |
1625 return !(InStartup() && chrome::ShouldPreferRemoteNTPOnStartup()); | 1628 return !(InStartup() && chrome::ShouldPreferRemoteNTPOnStartup()); |
1626 } | 1629 } |
1627 | 1630 |
1628 void InstantController::ResetOverlay(const std::string& instant_url) { | 1631 void InstantController::ResetOverlay(const std::string& instant_url) { |
1629 HideInternal(); | 1632 HideInternal(); |
1630 // If there's no active tab, the browser is opening or closing. | 1633 overlay_.reset(); |
1631 const content::WebContents* active_tab = browser_->GetActiveWebContents(); | |
1632 if (!active_tab || instant_url.empty()) { | |
1633 overlay_.reset(); | |
1634 } else { | |
1635 overlay_.reset(new InstantOverlay(this, instant_url)); | |
1636 overlay_->InitContents(browser_->profile(), active_tab); | |
1637 } | |
1638 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( | |
1639 "ResetOverlay: instant_url='%s'", instant_url.c_str())); | |
1640 } | 1634 } |
1641 | 1635 |
1642 InstantController::InstantFallbackReason | 1636 InstantController::InstantFallbackReason |
1643 InstantController::ShouldSwitchToLocalOverlay() const { | 1637 InstantController::ShouldSwitchToLocalOverlay() const { |
1644 if (!extended_enabled()) | 1638 if (!extended_enabled()) |
1645 return INSTANT_FALLBACK_NONE; | 1639 return INSTANT_FALLBACK_NONE; |
1646 | 1640 |
1647 if (!overlay()) | 1641 if (!overlay()) |
1648 return DetermineFallbackReason(NULL, std::string()); | 1642 return DetermineFallbackReason(NULL, std::string()); |
1649 | 1643 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1721 | 1715 |
1722 // Clear the first interaction timestamp for later use. | 1716 // Clear the first interaction timestamp for later use. |
1723 first_interaction_time_ = base::Time(); | 1717 first_interaction_time_ = base::Time(); |
1724 first_interaction_time_recorded_ = false; | 1718 first_interaction_time_recorded_ = false; |
1725 | 1719 |
1726 if (instant_tab_) | 1720 if (instant_tab_) |
1727 use_tab_for_suggestions_ = true; | 1721 use_tab_for_suggestions_ = true; |
1728 } | 1722 } |
1729 | 1723 |
1730 void InstantController::ShowOverlay(int height, InstantSizeUnits units) { | 1724 void InstantController::ShowOverlay(int height, InstantSizeUnits units) { |
| 1725 // Nothing to see here. |
| 1726 if (!overlay_) |
| 1727 return; |
| 1728 |
1731 // If we are on a committed search results page, the |overlay_| is not in use. | 1729 // If we are on a committed search results page, the |overlay_| is not in use. |
1732 if (UseTabForSuggestions()) | 1730 if (UseTabForSuggestions()) |
1733 return; | 1731 return; |
1734 | 1732 |
1735 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( | 1733 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( |
1736 "Show: height=%d units=%d", height, units)); | 1734 "Show: height=%d units=%d", height, units)); |
1737 | 1735 |
1738 // Must have updated omnibox after the last HideOverlay() to show suggestions. | 1736 // Must have updated omnibox after the last HideOverlay() to show suggestions. |
1739 if (!allow_overlay_to_show_search_suggestions_) | 1737 if (!allow_overlay_to_show_search_suggestions_) |
1740 return; | 1738 return; |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1911 bool js_webkit_enabled = profile()->GetPrefs()->GetBoolean( | 1909 bool js_webkit_enabled = profile()->GetPrefs()->GetBoolean( |
1912 prefs::kWebKitJavascriptEnabled); | 1910 prefs::kWebKitJavascriptEnabled); |
1913 return js_content_enabled && js_webkit_enabled; | 1911 return js_content_enabled && js_webkit_enabled; |
1914 } | 1912 } |
1915 | 1913 |
1916 bool InstantController::InStartup() const { | 1914 bool InstantController::InStartup() const { |
1917 // TODO(shishir): This is not completely reliable. Find a better way to detect | 1915 // TODO(shishir): This is not completely reliable. Find a better way to detect |
1918 // startup time. | 1916 // startup time. |
1919 return !browser_->GetActiveWebContents(); | 1917 return !browser_->GetActiveWebContents(); |
1920 } | 1918 } |
OLD | NEW |