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 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
664 results.push_back(result); | 664 results.push_back(result); |
665 } | 665 } |
666 } | 666 } |
667 } | 667 } |
668 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( | 668 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( |
669 "HandleAutocompleteResults: total_results=%d", | 669 "HandleAutocompleteResults: total_results=%d", |
670 static_cast<int>(results.size()))); | 670 static_cast<int>(results.size()))); |
671 | 671 |
672 if (UseTabForSuggestions()) | 672 if (UseTabForSuggestions()) |
673 instant_tab_->SendAutocompleteResults(results); | 673 instant_tab_->SendAutocompleteResults(results); |
674 else | 674 else if (overlay_) |
675 overlay_->SendAutocompleteResults(results); | 675 overlay_->SendAutocompleteResults(results); |
676 | 676 |
677 content::NotificationService::current()->Notify( | 677 content::NotificationService::current()->Notify( |
678 chrome::NOTIFICATION_INSTANT_SENT_AUTOCOMPLETE_RESULTS, | 678 chrome::NOTIFICATION_INSTANT_SENT_AUTOCOMPLETE_RESULTS, |
679 content::Source<InstantController>(this), | 679 content::Source<InstantController>(this), |
680 content::NotificationService::NoDetails()); | 680 content::NotificationService::NoDetails()); |
681 } | 681 } |
682 | 682 |
683 void InstantController::OnDefaultSearchProviderChanged() { | 683 void InstantController::OnDefaultSearchProviderChanged() { |
684 if (ntp_ && extended_enabled()) { | 684 if (ntp_ && extended_enabled()) { |
(...skipping 15 matching lines...) Expand all Loading... |
700 | 700 |
701 bool InstantController::OnUpOrDownKeyPressed(int count) { | 701 bool InstantController::OnUpOrDownKeyPressed(int count) { |
702 if (!extended_enabled()) | 702 if (!extended_enabled()) |
703 return false; | 703 return false; |
704 | 704 |
705 if (!UseTabForSuggestions() && !overlay_) | 705 if (!UseTabForSuggestions() && !overlay_) |
706 return false; | 706 return false; |
707 | 707 |
708 if (UseTabForSuggestions()) | 708 if (UseTabForSuggestions()) |
709 instant_tab_->UpOrDownKeyPressed(count); | 709 instant_tab_->UpOrDownKeyPressed(count); |
710 else | 710 else if (overlay_) |
711 overlay_->UpOrDownKeyPressed(count); | 711 overlay_->UpOrDownKeyPressed(count); |
712 | 712 |
713 return true; | 713 return true; |
714 } | 714 } |
715 | 715 |
716 void InstantController::OnCancel(const AutocompleteMatch& match, | 716 void InstantController::OnCancel(const AutocompleteMatch& match, |
717 const string16& user_text, | 717 const string16& user_text, |
718 const string16& full_text) { | 718 const string16& full_text) { |
719 if (!extended_enabled()) | 719 if (!extended_enabled()) |
720 return; | 720 return; |
721 | 721 |
722 if (!UseTabForSuggestions() && !overlay_) | 722 if (!UseTabForSuggestions() && !overlay_) |
723 return; | 723 return; |
724 | 724 |
725 // We manually reset the state here since the JS is not expected to do it. | 725 // We manually reset the state here since the JS is not expected to do it. |
726 // TODO(sreeram): Handle the case where user_text is now a URL | 726 // TODO(sreeram): Handle the case where user_text is now a URL |
727 last_match_was_search_ = AutocompleteMatch::IsSearchType(match.type) && | 727 last_match_was_search_ = AutocompleteMatch::IsSearchType(match.type) && |
728 !full_text.empty(); | 728 !full_text.empty(); |
729 last_omnibox_text_ = full_text; | 729 last_omnibox_text_ = full_text; |
730 last_user_text_ = user_text; | 730 last_user_text_ = user_text; |
731 last_suggestion_ = InstantSuggestion(); | 731 last_suggestion_ = InstantSuggestion(); |
732 | 732 |
733 // Say |full_text| is "amazon.com" and |user_text| is "ama". This means the | 733 // Say |full_text| is "amazon.com" and |user_text| is "ama". This means the |
734 // inline autocompletion is "zon.com"; so the selection should span from | 734 // inline autocompletion is "zon.com"; so the selection should span from |
735 // user_text.size() to full_text.size(). The selection bounds are inverted | 735 // user_text.size() to full_text.size(). The selection bounds are inverted |
736 // because the caret is at the end of |user_text|, not |full_text|. | 736 // because the caret is at the end of |user_text|, not |full_text|. |
737 if (UseTabForSuggestions()) { | 737 if (UseTabForSuggestions()) { |
738 instant_tab_->CancelSelection(user_text, full_text.size(), user_text.size(), | 738 instant_tab_->CancelSelection(user_text, full_text.size(), user_text.size(), |
739 last_verbatim_); | 739 last_verbatim_); |
740 } else { | 740 } else if (overlay_) { |
741 overlay_->CancelSelection(user_text, full_text.size(), user_text.size(), | 741 overlay_->CancelSelection(user_text, full_text.size(), user_text.size(), |
742 last_verbatim_); | 742 last_verbatim_); |
743 } | 743 } |
744 } | 744 } |
745 | 745 |
746 void InstantController::OmniboxNavigateToURL() { | 746 void InstantController::OmniboxNavigateToURL() { |
747 RecordNavigationHistogram(UsingLocalPage(), false, extended_enabled()); | 747 RecordNavigationHistogram(UsingLocalPage(), false, extended_enabled()); |
748 if (!extended_enabled()) | 748 if (!extended_enabled()) |
749 return; | 749 return; |
750 if (UseTabForSuggestions()) | 750 if (UseTabForSuggestions()) |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
843 last_suggestion_.behavior == INSTANT_COMPLETE_NEVER)) { | 843 last_suggestion_.behavior == INSTANT_COMPLETE_NEVER)) { |
844 last_suggestion_.text.clear(); | 844 last_suggestion_.text.clear(); |
845 instant_tab_->Submit(last_omnibox_text_); | 845 instant_tab_->Submit(last_omnibox_text_); |
846 instant_tab_->contents()->GetView()->Focus(); | 846 instant_tab_->contents()->GetView()->Focus(); |
847 EnsureSearchTermsAreSet(instant_tab_->contents(), last_omnibox_text_); | 847 EnsureSearchTermsAreSet(instant_tab_->contents(), last_omnibox_text_); |
848 return true; | 848 return true; |
849 } | 849 } |
850 return false; | 850 return false; |
851 } | 851 } |
852 | 852 |
| 853 if (!overlay_) |
| 854 return false; |
| 855 |
853 // If the overlay is not showing at all, don't commit it. | 856 // If the overlay is not showing at all, don't commit it. |
854 if (!model_.mode().is_search_suggestions()) | 857 if (!model_.mode().is_search_suggestions()) |
855 return false; | 858 return false; |
856 | 859 |
857 // If the overlay is showing at full height (with results), commit it. | 860 // If the overlay is showing at full height (with results), commit it. |
858 // If it's showing at parial height, commit if it's navigating. | 861 // If it's showing at parial height, commit if it's navigating. |
859 if (!IsOverlayingSearchResults() && type != INSTANT_COMMIT_NAVIGATED) | 862 if (!IsOverlayingSearchResults() && type != INSTANT_COMMIT_NAVIGATED) |
860 return false; | 863 return false; |
861 | 864 |
862 // There may re-entrance here, from the call to browser_->CommitInstant below, | 865 // 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... |
1116 return; | 1119 return; |
1117 | 1120 |
1118 // If the overlay is showing or the omnibox has focus, don't refresh the | 1121 // If the overlay is showing or the omnibox has focus, don't refresh the |
1119 // overlay. It will get refreshed the next time the overlay is hidden or the | 1122 // overlay. It will get refreshed the next time the overlay is hidden or the |
1120 // omnibox loses focus. | 1123 // omnibox loses focus. |
1121 if (omnibox_focus_state_ == OMNIBOX_FOCUS_NONE && model_.mode().is_default()) | 1124 if (omnibox_focus_state_ == OMNIBOX_FOCUS_NONE && model_.mode().is_default()) |
1122 ResetOverlay(GetInstantURL()); | 1125 ResetOverlay(GetInstantURL()); |
1123 } | 1126 } |
1124 | 1127 |
1125 void InstantController::OverlayLoadCompletedMainFrame() { | 1128 void InstantController::OverlayLoadCompletedMainFrame() { |
1126 if (overlay_->supports_instant()) | 1129 if (!overlay_ || overlay_->supports_instant()) |
1127 return; | 1130 return; |
1128 InstantService* instant_service = | 1131 InstantService* instant_service = |
1129 InstantServiceFactory::GetForProfile(browser_->profile()); | 1132 InstantServiceFactory::GetForProfile(browser_->profile()); |
1130 content::WebContents* contents = overlay_->contents(); | 1133 content::WebContents* contents = overlay_->contents(); |
1131 DCHECK(contents); | 1134 DCHECK(contents); |
1132 if (instant_service->IsInstantProcess( | 1135 if (instant_service->IsInstantProcess( |
1133 contents->GetRenderProcessHost()->GetID())) { | 1136 contents->GetRenderProcessHost()->GetID())) { |
1134 return; | 1137 return; |
1135 } | 1138 } |
1136 InstantSupportDetermined(contents, false); | 1139 InstantSupportDetermined(contents, false); |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1625 return false; | 1628 return false; |
1626 | 1629 |
1627 // The preloaded NTP does not support instant yet. If we're not in startup, | 1630 // The preloaded NTP does not support instant yet. If we're not in startup, |
1628 // always fall back to the local NTP. If we are in startup, use the local NTP | 1631 // always fall back to the local NTP. If we are in startup, use the local NTP |
1629 // (unless the finch flag to use the remote NTP is set). | 1632 // (unless the finch flag to use the remote NTP is set). |
1630 return !(InStartup() && chrome::ShouldPreferRemoteNTPOnStartup()); | 1633 return !(InStartup() && chrome::ShouldPreferRemoteNTPOnStartup()); |
1631 } | 1634 } |
1632 | 1635 |
1633 void InstantController::ResetOverlay(const std::string& instant_url) { | 1636 void InstantController::ResetOverlay(const std::string& instant_url) { |
1634 HideInternal(); | 1637 HideInternal(); |
1635 // If there's no active tab, the browser is opening or closing. | 1638 overlay_.reset(); |
1636 const content::WebContents* active_tab = browser_->GetActiveWebContents(); | |
1637 if (!active_tab || instant_url.empty()) { | |
1638 overlay_.reset(); | |
1639 } else { | |
1640 overlay_.reset(new InstantOverlay(this, instant_url)); | |
1641 overlay_->InitContents(browser_->profile(), active_tab); | |
1642 } | |
1643 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( | |
1644 "ResetOverlay: instant_url='%s'", instant_url.c_str())); | |
1645 } | 1639 } |
1646 | 1640 |
1647 InstantController::InstantFallbackReason | 1641 InstantController::InstantFallbackReason |
1648 InstantController::ShouldSwitchToLocalOverlay() const { | 1642 InstantController::ShouldSwitchToLocalOverlay() const { |
1649 if (!extended_enabled()) | 1643 if (!extended_enabled()) |
1650 return INSTANT_FALLBACK_NONE; | 1644 return INSTANT_FALLBACK_NONE; |
1651 | 1645 |
1652 if (!overlay()) | 1646 if (!overlay()) |
1653 return DetermineFallbackReason(NULL, std::string()); | 1647 return DetermineFallbackReason(NULL, std::string()); |
1654 | 1648 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1726 | 1720 |
1727 // Clear the first interaction timestamp for later use. | 1721 // Clear the first interaction timestamp for later use. |
1728 first_interaction_time_ = base::Time(); | 1722 first_interaction_time_ = base::Time(); |
1729 first_interaction_time_recorded_ = false; | 1723 first_interaction_time_recorded_ = false; |
1730 | 1724 |
1731 if (instant_tab_) | 1725 if (instant_tab_) |
1732 use_tab_for_suggestions_ = true; | 1726 use_tab_for_suggestions_ = true; |
1733 } | 1727 } |
1734 | 1728 |
1735 void InstantController::ShowOverlay(int height, InstantSizeUnits units) { | 1729 void InstantController::ShowOverlay(int height, InstantSizeUnits units) { |
| 1730 // Nothing to see here. |
| 1731 if (!overlay_) |
| 1732 return; |
| 1733 |
1736 // If we are on a committed search results page, the |overlay_| is not in use. | 1734 // If we are on a committed search results page, the |overlay_| is not in use. |
1737 if (UseTabForSuggestions()) | 1735 if (UseTabForSuggestions()) |
1738 return; | 1736 return; |
1739 | 1737 |
1740 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( | 1738 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( |
1741 "Show: height=%d units=%d", height, units)); | 1739 "Show: height=%d units=%d", height, units)); |
1742 | 1740 |
1743 // Must have updated omnibox after the last HideOverlay() to show suggestions. | 1741 // Must have updated omnibox after the last HideOverlay() to show suggestions. |
1744 if (!allow_overlay_to_show_search_suggestions_) | 1742 if (!allow_overlay_to_show_search_suggestions_) |
1745 return; | 1743 return; |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1916 bool js_webkit_enabled = profile()->GetPrefs()->GetBoolean( | 1914 bool js_webkit_enabled = profile()->GetPrefs()->GetBoolean( |
1917 prefs::kWebKitJavascriptEnabled); | 1915 prefs::kWebKitJavascriptEnabled); |
1918 return js_content_enabled && js_webkit_enabled; | 1916 return js_content_enabled && js_webkit_enabled; |
1919 } | 1917 } |
1920 | 1918 |
1921 bool InstantController::InStartup() const { | 1919 bool InstantController::InStartup() const { |
1922 // TODO(shishir): This is not completely reliable. Find a better way to detect | 1920 // TODO(shishir): This is not completely reliable. Find a better way to detect |
1923 // startup time. | 1921 // startup time. |
1924 return !browser_->GetActiveWebContents(); | 1922 return !browser_->GetActiveWebContents(); |
1925 } | 1923 } |
OLD | NEW |