Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: chrome/browser/ui/omnibox/omnibox_edit_model.cc

Issue 14358005: Omnibox refactor, moved OnResultChanged to OmniboxController (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/omnibox/omnibox_edit_model.h" 5 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/auto_reset.h" 9 #include "base/auto_reset.h"
10 #include "base/format_macros.h" 10 #include "base/format_macros.h"
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 OmniboxEditModel::State::~State() { 113 OmniboxEditModel::State::~State() {
114 } 114 }
115 115
116 /////////////////////////////////////////////////////////////////////////////// 116 ///////////////////////////////////////////////////////////////////////////////
117 // OmniboxEditModel 117 // OmniboxEditModel
118 118
119 OmniboxEditModel::OmniboxEditModel(OmniboxView* view, 119 OmniboxEditModel::OmniboxEditModel(OmniboxView* view,
120 OmniboxEditController* controller, 120 OmniboxEditController* controller,
121 Profile* profile) 121 Profile* profile)
122 : view_(view), 122 : view_(view),
123 popup_(NULL),
124 controller_(controller), 123 controller_(controller),
125 focus_state_(OMNIBOX_FOCUS_NONE), 124 focus_state_(OMNIBOX_FOCUS_NONE),
126 user_input_in_progress_(false), 125 user_input_in_progress_(false),
127 just_deleted_text_(false), 126 just_deleted_text_(false),
128 has_temporary_text_(false), 127 has_temporary_text_(false),
129 is_temporary_text_set_by_instant_(false), 128 is_temporary_text_set_by_instant_(false),
130 paste_state_(NONE), 129 paste_state_(NONE),
131 control_key_state_(UP), 130 control_key_state_(UP),
132 is_keyword_hint_(false), 131 is_keyword_hint_(false),
133 profile_(profile), 132 profile_(profile),
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 223
225 void OmniboxEditModel::FinalizeInstantQuery(const string16& input_text, 224 void OmniboxEditModel::FinalizeInstantQuery(const string16& input_text,
226 const InstantSuggestion& suggestion, 225 const InstantSuggestion& suggestion,
227 bool skip_inline_autocomplete) { 226 bool skip_inline_autocomplete) {
228 if (skip_inline_autocomplete) { 227 if (skip_inline_autocomplete) {
229 const string16 final_text = input_text + suggestion.text; 228 const string16 final_text = input_text + suggestion.text;
230 view_->OnBeforePossibleChange(); 229 view_->OnBeforePossibleChange();
231 view_->SetWindowTextAndCaretPos(final_text, final_text.length(), false, 230 view_->SetWindowTextAndCaretPos(final_text, final_text.length(), false,
232 false); 231 false);
233 view_->OnAfterPossibleChange(); 232 view_->OnAfterPossibleChange();
234 } else if (popup_->IsOpen()) { 233 } else if (popup_model()->IsOpen()) {
235 SearchProvider* search_provider = 234 SearchProvider* search_provider =
236 autocomplete_controller()->search_provider(); 235 autocomplete_controller()->search_provider();
237 // There may be no providers during testing; guard against that. 236 // There may be no providers during testing; guard against that.
238 if (search_provider) 237 if (search_provider)
239 search_provider->FinalizeInstantQuery(input_text, suggestion); 238 search_provider->FinalizeInstantQuery(input_text, suggestion);
240 } 239 }
241 } 240 }
242 241
243 void OmniboxEditModel::SetInstantSuggestion( 242 void OmniboxEditModel::SetInstantSuggestion(
244 const InstantSuggestion& suggestion) { 243 const InstantSuggestion& suggestion) {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 // has been closed or on return from a sleep state. 334 // has been closed or on return from a sleep state.
336 // (http://crbug.com/105689) 335 // (http://crbug.com/105689)
337 if (!delegate_->CurrentPageExists()) 336 if (!delegate_->CurrentPageExists())
338 break; 337 break;
339 // Ask for prerendering if the destination URL is different than the 338 // Ask for prerendering if the destination URL is different than the
340 // current URL. 339 // current URL.
341 if (current_match.destination_url != PermanentURL()) 340 if (current_match.destination_url != PermanentURL())
342 delegate_->DoPrerender(current_match); 341 delegate_->DoPrerender(current_match);
343 break; 342 break;
344 case AutocompleteActionPredictor::ACTION_PRECONNECT: 343 case AutocompleteActionPredictor::ACTION_PRECONNECT:
345 DoPreconnect(current_match); 344 omnibox_controller_->DoPreconnect(current_match);
346 break; 345 break;
347 case AutocompleteActionPredictor::ACTION_NONE: 346 case AutocompleteActionPredictor::ACTION_NONE:
348 break; 347 break;
349 } 348 }
350 349
351 controller_->OnChanged(); 350 controller_->OnChanged();
352 } 351 }
353 352
354 void OmniboxEditModel::GetDataForURLExport(GURL* url, 353 void OmniboxEditModel::GetDataForURLExport(GURL* url,
355 string16* title, 354 string16* title,
(...skipping 18 matching lines...) Expand all
374 #endif 373 #endif
375 374
376 // The value of input.prevent_inline_autocomplete() is determined by the 375 // The value of input.prevent_inline_autocomplete() is determined by the
377 // following conditions: 376 // following conditions:
378 // 1. If the caret is at the end of the text. 377 // 1. If the caret is at the end of the text.
379 // 2. If it's in IME composition mode. 378 // 2. If it's in IME composition mode.
380 // We send the caret position to Instant (so it can determine #1 itself), and 379 // We send the caret position to Instant (so it can determine #1 itself), and
381 // we use a separated widget for displaying the Instant suggest (so it doesn't 380 // we use a separated widget for displaying the Instant suggest (so it doesn't
382 // interfere with #2). So, we don't need to care about the value of 381 // interfere with #2). So, we don't need to care about the value of
383 // input.prevent_inline_autocomplete() here. 382 // input.prevent_inline_autocomplete() here.
384 return view_->DeleteAtEndPressed() || popup_->selected_line() != 0 || 383 return view_->DeleteAtEndPressed() || popup_model()->selected_line() != 0 ||
385 just_deleted_text_; 384 just_deleted_text_;
386 } 385 }
387 386
388 bool OmniboxEditModel::CurrentTextIsURL() const { 387 bool OmniboxEditModel::CurrentTextIsURL() const {
389 if (view_->toolbar_model()->WouldReplaceSearchURLWithSearchTerms()) 388 if (view_->toolbar_model()->WouldReplaceSearchURLWithSearchTerms())
390 return false; 389 return false;
391 390
392 // If current text is not composed of replaced search terms and 391 // If current text is not composed of replaced search terms and
393 // !user_input_in_progress_, then permanent text is showing and should be a 392 // !user_input_in_progress_, then permanent text is showing and should be a
394 // URL, so no further checking is needed. By avoiding checking in this case, 393 // URL, so no further checking is needed. By avoiding checking in this case,
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 if (action_predictor) 486 if (action_predictor)
488 action_predictor->ClearTransitionalMatches(); 487 action_predictor->ClearTransitionalMatches();
489 } 488 }
490 489
491 void OmniboxEditModel::StartAutocomplete( 490 void OmniboxEditModel::StartAutocomplete(
492 bool has_selected_text, 491 bool has_selected_text,
493 bool prevent_inline_autocomplete) const { 492 bool prevent_inline_autocomplete) const {
494 ClearPopupKeywordMode(); 493 ClearPopupKeywordMode();
495 494
496 bool keyword_is_selected = KeywordIsSelected(); 495 bool keyword_is_selected = KeywordIsSelected();
497 popup_->SetHoveredLine(OmniboxPopupModel::kNoMatch); 496 popup_model()->SetHoveredLine(OmniboxPopupModel::kNoMatch);
498 497
499 size_t cursor_position; 498 size_t cursor_position;
500 if (inline_autocomplete_text_.empty()) { 499 if (inline_autocomplete_text_.empty()) {
501 // Cursor position is equivalent to the current selection's end. 500 // Cursor position is equivalent to the current selection's end.
502 size_t start; 501 size_t start;
503 view_->GetSelectionBounds(&start, &cursor_position); 502 view_->GetSelectionBounds(&start, &cursor_position);
504 // Adjust cursor position taking into account possible keyword in the user 503 // Adjust cursor position taking into account possible keyword in the user
505 // text. We rely on DisplayTextFromUserText() method which is consistent 504 // text. We rely on DisplayTextFromUserText() method which is consistent
506 // with keyword extraction done in KeywordProvider/SearchProvider. 505 // with keyword extraction done in KeywordProvider/SearchProvider.
507 const size_t cursor_offset = 506 const size_t cursor_offset =
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 view_->OpenMatch(match, disposition, alternate_nav_url, 628 view_->OpenMatch(match, disposition, alternate_nav_url,
630 OmniboxPopupModel::kNoMatch); 629 OmniboxPopupModel::kNoMatch);
631 } 630 }
632 631
633 void OmniboxEditModel::OpenMatch(const AutocompleteMatch& match, 632 void OmniboxEditModel::OpenMatch(const AutocompleteMatch& match,
634 WindowOpenDisposition disposition, 633 WindowOpenDisposition disposition,
635 const GURL& alternate_nav_url, 634 const GURL& alternate_nav_url,
636 size_t index) { 635 size_t index) {
637 // We only care about cases where there is a selection (i.e. the popup is 636 // We only care about cases where there is a selection (i.e. the popup is
638 // open). 637 // open).
639 if (popup_->IsOpen()) { 638 if (popup_model()->IsOpen()) {
640 const base::TimeTicks& now(base::TimeTicks::Now()); 639 const base::TimeTicks& now(base::TimeTicks::Now());
641 // TODO(sreeram): Handle is_temporary_text_set_by_instant_ correctly. 640 // TODO(sreeram): Handle is_temporary_text_set_by_instant_ correctly.
642 AutocompleteLog log( 641 AutocompleteLog log(
643 autocomplete_controller()->input().text(), 642 autocomplete_controller()->input().text(),
644 just_deleted_text_, 643 just_deleted_text_,
645 autocomplete_controller()->input().type(), 644 autocomplete_controller()->input().type(),
646 popup_->selected_line(), 645 popup_model()->selected_line(),
647 -1, // don't yet know tab ID; set later if appropriate 646 -1, // don't yet know tab ID; set later if appropriate
648 delegate_->CurrentPageExists() ? ClassifyPage(delegate_->GetURL()) : 647 delegate_->CurrentPageExists() ? ClassifyPage(delegate_->GetURL()) :
649 metrics::OmniboxEventProto_PageClassification_OTHER, 648 metrics::OmniboxEventProto_PageClassification_OTHER,
650 now - time_user_first_modified_omnibox_, 649 now - time_user_first_modified_omnibox_,
651 string16::npos, // completed_length; possibly set later 650 string16::npos, // completed_length; possibly set later
652 now - autocomplete_controller()->last_time_default_match_changed(), 651 now - autocomplete_controller()->last_time_default_match_changed(),
653 result()); 652 result());
654 DCHECK(user_input_in_progress_ || 653 DCHECK(user_input_in_progress_ ||
655 match.provider->type() == AutocompleteProvider::TYPE_ZERO_SUGGEST) 654 match.provider->type() == AutocompleteProvider::TYPE_ZERO_SUGGEST)
656 << "We didn't get here through the expected series of calls. " 655 << "We didn't get here through the expected series of calls. "
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
754 if (match.starred) 753 if (match.starred)
755 bookmark_utils::RecordBookmarkLaunch(bookmark_utils::LAUNCH_OMNIBOX); 754 bookmark_utils::RecordBookmarkLaunch(bookmark_utils::LAUNCH_OMNIBOX);
756 } 755 }
757 756
758 bool OmniboxEditModel::AcceptKeyword(EnteredKeywordModeMethod entered_method) { 757 bool OmniboxEditModel::AcceptKeyword(EnteredKeywordModeMethod entered_method) {
759 DCHECK(is_keyword_hint_ && !keyword_.empty()); 758 DCHECK(is_keyword_hint_ && !keyword_.empty());
760 759
761 autocomplete_controller()->Stop(false); 760 autocomplete_controller()->Stop(false);
762 is_keyword_hint_ = false; 761 is_keyword_hint_ = false;
763 762
764 if (popup_->IsOpen()) 763 if (popup_model()->IsOpen())
765 popup_->SetSelectedLineState(OmniboxPopupModel::KEYWORD); 764 popup_model()->SetSelectedLineState(OmniboxPopupModel::KEYWORD);
766 else 765 else
767 StartAutocomplete(false, true); 766 StartAutocomplete(false, true);
768 767
769 // Ensure the current selection is saved before showing keyword mode 768 // Ensure the current selection is saved before showing keyword mode
770 // so that moving to another line and then reverting the text will restore 769 // so that moving to another line and then reverting the text will restore
771 // the current state properly. 770 // the current state properly.
772 bool save_original_selection = !has_temporary_text_; 771 bool save_original_selection = !has_temporary_text_;
773 has_temporary_text_ = true; 772 has_temporary_text_ = true;
774 is_temporary_text_set_by_instant_ = false; 773 is_temporary_text_set_by_instant_ = false;
775 view_->OnTemporaryTextMaybeChanged( 774 view_->OnTemporaryTextMaybeChanged(
776 DisplayTextFromUserText(CurrentMatch().fill_into_edit), 775 DisplayTextFromUserText(CurrentMatch().fill_into_edit),
777 save_original_selection, true); 776 save_original_selection, true);
778 777
779 content::RecordAction(UserMetricsAction("AcceptedKeywordHint")); 778 content::RecordAction(UserMetricsAction("AcceptedKeywordHint"));
780 UMA_HISTOGRAM_ENUMERATION(kEnteredKeywordModeHistogram, entered_method, 779 UMA_HISTOGRAM_ENUMERATION(kEnteredKeywordModeHistogram, entered_method,
781 ENTERED_KEYWORD_MODE_NUM_ITEMS); 780 ENTERED_KEYWORD_MODE_NUM_ITEMS);
782 781
783 return true; 782 return true;
784 } 783 }
785 784
785 void OmniboxEditModel::AcceptTemporaryTextAsUserText() {
786 InternalSetUserText(UserTextFromDisplayText(view_->GetText()));
787 has_temporary_text_ = false;
788 is_temporary_text_set_by_instant_ = false;
789 OnPopupBoundsChanged(gfx::Rect());
790 delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_);
791 }
792
786 void OmniboxEditModel::ClearKeyword(const string16& visible_text) { 793 void OmniboxEditModel::ClearKeyword(const string16& visible_text) {
787 autocomplete_controller()->Stop(false); 794 autocomplete_controller()->Stop(false);
788 ClearPopupKeywordMode(); 795 ClearPopupKeywordMode();
789 796
790 const string16 window_text(keyword_ + visible_text); 797 const string16 window_text(keyword_ + visible_text);
791 798
792 // Only reset the result if the edit text has changed since the 799 // Only reset the result if the edit text has changed since the
793 // keyword was accepted, or if the popup is closed. 800 // keyword was accepted, or if the popup is closed.
794 if (just_deleted_text_ || !visible_text.empty() || !popup_->IsOpen()) { 801 if (just_deleted_text_ || !visible_text.empty() || !popup_model()->IsOpen()) {
795 view_->OnBeforePossibleChange(); 802 view_->OnBeforePossibleChange();
796 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(), 803 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(),
797 false, false); 804 false, false);
798 keyword_.clear(); 805 keyword_.clear();
799 is_keyword_hint_ = false; 806 is_keyword_hint_ = false;
800 view_->OnAfterPossibleChange(); 807 view_->OnAfterPossibleChange();
801 just_deleted_text_ = true; // OnAfterPossibleChange() fails to clear this 808 just_deleted_text_ = true; // OnAfterPossibleChange() fails to clear this
802 // since the edit contents have actually grown 809 // since the edit contents have actually grown
803 // longer. 810 // longer.
804 } else { 811 } else {
805 is_keyword_hint_ = true; 812 is_keyword_hint_ = true;
806 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(), 813 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(),
807 false, true); 814 false, true);
808 } 815 }
809 } 816 }
810 817
811 const AutocompleteResult& OmniboxEditModel::result() const {
812 return autocomplete_controller()->result();
813 }
814
815 void OmniboxEditModel::OnSetFocus(bool control_down) { 818 void OmniboxEditModel::OnSetFocus(bool control_down) {
816 // If the omnibox lost focus while the caret was hidden and then regained 819 // If the omnibox lost focus while the caret was hidden and then regained
817 // focus, OnSetFocus() is called and should restore visibility. Note that 820 // focus, OnSetFocus() is called and should restore visibility. Note that
818 // focus can be regained without an accompanying call to 821 // focus can be regained without an accompanying call to
819 // OmniboxView::SetFocus(), e.g. by tabbing in. 822 // OmniboxView::SetFocus(), e.g. by tabbing in.
820 SetFocusState(OMNIBOX_FOCUS_VISIBLE, OMNIBOX_FOCUS_CHANGE_EXPLICIT); 823 SetFocusState(OMNIBOX_FOCUS_VISIBLE, OMNIBOX_FOCUS_CHANGE_EXPLICIT);
821 control_key_state_ = control_down ? DOWN_WITHOUT_CHANGE : UP; 824 control_key_state_ = control_down ? DOWN_WITHOUT_CHANGE : UP;
822 825
823 if (delegate_->CurrentPageExists()) { 826 if (delegate_->CurrentPageExists()) {
824 // TODO(jered): We may want to merge this into Start() and just call that 827 // TODO(jered): We may want to merge this into Start() and just call that
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
905 if (pressed == (control_key_state_ == UP)) { 908 if (pressed == (control_key_state_ == UP)) {
906 ControlKeyState old_state = control_key_state_; 909 ControlKeyState old_state = control_key_state_;
907 control_key_state_ = pressed ? DOWN_WITHOUT_CHANGE : UP; 910 control_key_state_ = pressed ? DOWN_WITHOUT_CHANGE : UP;
908 if ((control_key_state_ == DOWN_WITHOUT_CHANGE) && has_temporary_text_) { 911 if ((control_key_state_ == DOWN_WITHOUT_CHANGE) && has_temporary_text_) {
909 // Arrowing down and then hitting control accepts the temporary text as 912 // Arrowing down and then hitting control accepts the temporary text as
910 // the input text. 913 // the input text.
911 InternalSetUserText(UserTextFromDisplayText(view_->GetText())); 914 InternalSetUserText(UserTextFromDisplayText(view_->GetText()));
912 has_temporary_text_ = false; 915 has_temporary_text_ = false;
913 is_temporary_text_set_by_instant_ = false; 916 is_temporary_text_set_by_instant_ = false;
914 } 917 }
915 if ((old_state != DOWN_WITH_CHANGE) && popup_->IsOpen()) { 918 if ((old_state != DOWN_WITH_CHANGE) && popup_model()->IsOpen()) {
916 // Autocomplete history provider results may change, so refresh the 919 // Autocomplete history provider results may change, so refresh the
917 // popup. This will force user_input_in_progress_ to true, but if the 920 // popup. This will force user_input_in_progress_ to true, but if the
918 // popup is open, that should have already been the case. 921 // popup is open, that should have already been the case.
919 view_->UpdatePopup(); 922 view_->UpdatePopup();
920 } 923 }
921 } 924 }
922 } 925 }
923 926
924 void OmniboxEditModel::OnUpOrDownKeyPressed(int count) { 927 void OmniboxEditModel::OnUpOrDownKeyPressed(int count) {
925 // NOTE: This purposefully doesn't trigger any code that resets paste_state_. 928 // NOTE: This purposefully doesn't trigger any code that resets paste_state_.
926 if (!popup_->IsOpen()) { 929 if (!popup_model()->IsOpen()) {
927 if (!query_in_progress()) { 930 if (!query_in_progress()) {
928 // The popup is neither open nor working on a query already. So, start an 931 // The popup is neither open nor working on a query already. So, start an
929 // autocomplete query for the current text. This also sets 932 // autocomplete query for the current text. This also sets
930 // user_input_in_progress_ to true, which we want: if the user has started 933 // user_input_in_progress_ to true, which we want: if the user has started
931 // to interact with the popup, changing the permanent_text_ shouldn't 934 // to interact with the popup, changing the permanent_text_ shouldn't
932 // change the displayed text. 935 // change the displayed text.
933 // Note: This does not force the popup to open immediately. 936 // Note: This does not force the popup to open immediately.
934 // TODO(pkasting): We should, in fact, force this particular query to open 937 // TODO(pkasting): We should, in fact, force this particular query to open
935 // the popup immediately. 938 // the popup immediately.
936 if (!user_input_in_progress_) 939 if (!user_input_in_progress_)
937 InternalSetUserText(permanent_text_); 940 InternalSetUserText(permanent_text_);
938 view_->UpdatePopup(); 941 view_->UpdatePopup();
939 } else { 942 } else {
940 // TODO(pkasting): The popup is working on a query but is not open. We 943 // TODO(pkasting): The popup is working on a query but is not open. We
941 // should force it to open immediately. 944 // should force it to open immediately.
942 } 945 }
943 } else { 946 } else {
944 InstantController* instant = controller_->GetInstant(); 947 InstantController* instant = controller_->GetInstant();
945 if (instant && instant->OnUpOrDownKeyPressed(count)) { 948 if (instant && instant->OnUpOrDownKeyPressed(count)) {
946 // If Instant handles the key press, it's showing a list of suggestions 949 // If Instant handles the key press, it's showing a list of suggestions
947 // that it's stepping through. In that case, our popup model is 950 // that it's stepping through. In that case, our popup model is
948 // irrelevant, so don't process the key press ourselves. However, do stop 951 // irrelevant, so don't process the key press ourselves. However, do stop
949 // the autocomplete system from changing the results. 952 // the autocomplete system from changing the results.
950 autocomplete_controller()->Stop(false); 953 autocomplete_controller()->Stop(false);
951 } else { 954 } else {
952 // The popup is open, so the user should be able to interact with it 955 // The popup is open, so the user should be able to interact with it
953 // normally. 956 // normally.
954 popup_->Move(count); 957 popup_model()->Move(count);
955 } 958 }
956 } 959 }
957 } 960 }
958 961
959 void OmniboxEditModel::OnPopupDataChanged( 962 void OmniboxEditModel::OnPopupDataChanged(
960 const string16& text, 963 const string16& text,
961 GURL* destination_for_temporary_text_change, 964 GURL* destination_for_temporary_text_change,
962 const string16& keyword, 965 const string16& keyword,
963 bool is_keyword_hint) { 966 bool is_keyword_hint) {
964 // Update keyword/hint-related local state. 967 // Update keyword/hint-related local state.
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
1064 // Modifying the selection counts as accepting the autocompleted text. 1067 // Modifying the selection counts as accepting the autocompleted text.
1065 const bool user_text_changed = 1068 const bool user_text_changed =
1066 text_differs || (selection_differs && !inline_autocomplete_text_.empty()); 1069 text_differs || (selection_differs && !inline_autocomplete_text_.empty());
1067 1070
1068 // If something has changed while the control key is down, prevent 1071 // If something has changed while the control key is down, prevent
1069 // "ctrl-enter" until the control key is released. When we do this, we need 1072 // "ctrl-enter" until the control key is released. When we do this, we need
1070 // to update the popup if it's open, since the desired_tld will have changed. 1073 // to update the popup if it's open, since the desired_tld will have changed.
1071 if ((text_differs || selection_differs) && 1074 if ((text_differs || selection_differs) &&
1072 (control_key_state_ == DOWN_WITHOUT_CHANGE)) { 1075 (control_key_state_ == DOWN_WITHOUT_CHANGE)) {
1073 control_key_state_ = DOWN_WITH_CHANGE; 1076 control_key_state_ = DOWN_WITH_CHANGE;
1074 if (!text_differs && !popup_->IsOpen()) 1077 if (!text_differs && !popup_model()->IsOpen())
1075 return false; // Don't open the popup for no reason. 1078 return false; // Don't open the popup for no reason.
1076 } else if (!user_text_changed) { 1079 } else if (!user_text_changed) {
1077 return false; 1080 return false;
1078 } 1081 }
1079 1082
1080 // If the user text has not changed, we do not want to change the model's 1083 // If the user text has not changed, we do not want to change the model's
1081 // state associated with the text. Otherwise, we can get surprising behavior 1084 // state associated with the text. Otherwise, we can get surprising behavior
1082 // where the autocompleted text unexpectedly reappears, e.g. crbug.com/55983 1085 // where the autocompleted text unexpectedly reappears, e.g. crbug.com/55983
1083 if (user_text_changed) { 1086 if (user_text_changed) {
1084 InternalSetUserText(UserTextFromDisplayText(new_text)); 1087 InternalSetUserText(UserTextFromDisplayText(new_text));
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1135 MaybeAcceptKeywordBySpace(user_text_)); 1138 MaybeAcceptKeywordBySpace(user_text_));
1136 } 1139 }
1137 1140
1138 void OmniboxEditModel::OnPopupBoundsChanged(const gfx::Rect& bounds) { 1141 void OmniboxEditModel::OnPopupBoundsChanged(const gfx::Rect& bounds) {
1139 InstantController* instant = controller_->GetInstant(); 1142 InstantController* instant = controller_->GetInstant();
1140 if (instant) 1143 if (instant)
1141 instant->SetPopupBounds(bounds); 1144 instant->SetPopupBounds(bounds);
1142 } 1145 }
1143 1146
1144 void OmniboxEditModel::OnResultChanged(bool default_match_changed) { 1147 void OmniboxEditModel::OnResultChanged(bool default_match_changed) {
1145 const bool was_open = popup_->IsOpen();
1146 if (default_match_changed) {
1147 string16 inline_autocomplete_text;
1148 string16 keyword;
1149 bool is_keyword_hint = false;
1150 const AutocompleteResult& result = this->result();
1151 const AutocompleteResult::const_iterator match(result.default_match());
1152 if (match != result.end()) {
1153 if ((match->inline_autocomplete_offset != string16::npos) &&
1154 (match->inline_autocomplete_offset <
1155 match->fill_into_edit.length())) {
1156 inline_autocomplete_text =
1157 match->fill_into_edit.substr(match->inline_autocomplete_offset);
1158 }
1159
1160 if (!prerender::IsOmniboxEnabled(profile_))
1161 DoPreconnect(*match);
1162
1163 // We could prefetch the alternate nav URL, if any, but because there
1164 // can be many of these as a user types an initial series of characters,
1165 // the OS DNS cache could suffer eviction problems for minimal gain.
1166
1167 match->GetKeywordUIState(profile_, &keyword, &is_keyword_hint);
1168 }
1169
1170 popup_->OnResultChanged();
1171 OnPopupDataChanged(inline_autocomplete_text, NULL, keyword,
1172 is_keyword_hint);
1173 } else {
1174 popup_->OnResultChanged();
1175 }
1176
1177 if (popup_->IsOpen()) {
1178 OnPopupBoundsChanged(popup_->view()->GetTargetBounds());
1179
1180 InstantController* instant = controller_->GetInstant();
1181 if (instant && !in_revert_) {
1182 instant->HandleAutocompleteResults(
1183 *autocomplete_controller_->providers());
1184 }
1185 } else if (was_open) {
1186 // Accepts the temporary text as the user text, because it makes little
1187 // sense to have temporary text when the popup is closed.
1188 InternalSetUserText(UserTextFromDisplayText(view_->GetText()));
1189 has_temporary_text_ = false;
1190 is_temporary_text_set_by_instant_ = false;
1191 OnPopupBoundsChanged(gfx::Rect());
1192 delegate_->NotifySearchTabHelper(user_input_in_progress_, !in_revert_);
1193 }
1194 } 1148 }
1195 1149
1196 bool OmniboxEditModel::query_in_progress() const { 1150 bool OmniboxEditModel::query_in_progress() const {
1197 return !autocomplete_controller()->done(); 1151 return !autocomplete_controller()->done();
1198 } 1152 }
1199 1153
1200 void OmniboxEditModel::InternalSetUserText(const string16& text) { 1154 void OmniboxEditModel::InternalSetUserText(const string16& text) {
1201 user_text_ = text; 1155 user_text_ = text;
1202 just_deleted_text_ = false; 1156 just_deleted_text_ = false;
1203 inline_autocomplete_text_.clear(); 1157 inline_autocomplete_text_.clear();
1204 } 1158 }
1205 1159
1206 bool OmniboxEditModel::KeywordIsSelected() const { 1160 bool OmniboxEditModel::KeywordIsSelected() const {
1207 return !is_keyword_hint_ && !keyword_.empty(); 1161 return !is_keyword_hint_ && !keyword_.empty();
1208 } 1162 }
1209 1163
1210 void OmniboxEditModel::ClearPopupKeywordMode() const {
1211 if (popup_->IsOpen() &&
1212 popup_->selected_line_state() == OmniboxPopupModel::KEYWORD)
1213 popup_->SetSelectedLineState(OmniboxPopupModel::NORMAL);
1214 }
1215
1216 string16 OmniboxEditModel::DisplayTextFromUserText(const string16& text) const { 1164 string16 OmniboxEditModel::DisplayTextFromUserText(const string16& text) const {
1217 return KeywordIsSelected() ? 1165 return KeywordIsSelected() ?
1218 KeywordProvider::SplitReplacementStringFromInput(text, false) : text; 1166 KeywordProvider::SplitReplacementStringFromInput(text, false) : text;
1219 } 1167 }
1220 1168
1221 string16 OmniboxEditModel::UserTextFromDisplayText(const string16& text) const { 1169 string16 OmniboxEditModel::UserTextFromDisplayText(const string16& text) const {
1222 return KeywordIsSelected() ? (keyword_ + char16(' ') + text) : text; 1170 return KeywordIsSelected() ? (keyword_ + char16(' ') + text) : text;
1223 } 1171 }
1224 1172
1225 void OmniboxEditModel::InfoForCurrentSelection(AutocompleteMatch* match,
1226 GURL* alternate_nav_url) const {
1227 DCHECK(match != NULL);
1228 const AutocompleteResult& result = this->result();
1229 if (!autocomplete_controller()->done()) {
1230 // It's technically possible for |result| to be empty if no provider returns
1231 // a synchronous result but the query has not completed synchronously;
1232 // pratically, however, that should never actually happen.
1233 if (result.empty())
1234 return;
1235 // The user cannot have manually selected a match, or the query would have
1236 // stopped. So the default match must be the desired selection.
1237 *match = *result.default_match();
1238 } else {
1239 CHECK(popup_->IsOpen());
1240 // If there are no results, the popup should be closed (so we should have
1241 // failed the CHECK above), and URLsForDefaultMatch() should have been
1242 // called instead.
1243 CHECK(!result.empty());
1244 CHECK(popup_->selected_line() < result.size());
1245 *match = result.match_at(popup_->selected_line());
1246 }
1247 if (alternate_nav_url && popup_->manually_selected_match().empty())
1248 *alternate_nav_url = result.alternate_nav_url();
1249 }
1250
1251 void OmniboxEditModel::GetInfoForCurrentText(AutocompleteMatch* match, 1173 void OmniboxEditModel::GetInfoForCurrentText(AutocompleteMatch* match,
1252 GURL* alternate_nav_url) const { 1174 GURL* alternate_nav_url) const {
1253 // If there's temporary text and it has been set by Instant, we won't find it 1175 // If there's temporary text and it has been set by Instant, we won't find it
1254 // in the popup model, so classify the text anew. 1176 // in the popup model, so classify the text anew.
1255 if ((popup_->IsOpen() || query_in_progress()) && 1177 if ((popup_model()->IsOpen() || query_in_progress()) &&
1256 !is_temporary_text_set_by_instant_) { 1178 !is_temporary_text_set_by_instant_) {
1257 InfoForCurrentSelection(match, alternate_nav_url); 1179 InfoForCurrentSelection(match, alternate_nav_url);
1258 } else { 1180 } else {
1259 AutocompleteClassifierFactory::GetForProfile(profile_)->Classify( 1181 AutocompleteClassifierFactory::GetForProfile(profile_)->Classify(
1260 UserTextFromDisplayText(view_->GetText()), KeywordIsSelected(), true, 1182 UserTextFromDisplayText(view_->GetText()), KeywordIsSelected(), true,
1261 match, alternate_nav_url); 1183 match, alternate_nav_url);
1262 } 1184 }
1263 } 1185 }
1264 1186
1265 void OmniboxEditModel::RevertTemporaryText(bool revert_popup) { 1187 void OmniboxEditModel::RevertTemporaryText(bool revert_popup) {
(...skipping 17 matching lines...) Expand all
1283 // The two "false" arguments make sure that our shenanigans don't cause any 1205 // The two "false" arguments make sure that our shenanigans don't cause any
1284 // previously saved selection to be erased nor OnChanged() to be called. 1206 // previously saved selection to be erased nor OnChanged() to be called.
1285 view_->OnTemporaryTextMaybeChanged(user_text_ + inline_autocomplete_text_, 1207 view_->OnTemporaryTextMaybeChanged(user_text_ + inline_autocomplete_text_,
1286 false, false); 1208 false, false);
1287 AutocompleteResult::const_iterator match(result().default_match()); 1209 AutocompleteResult::const_iterator match(result().default_match());
1288 instant->OnCancel(match != result().end() ? *match : AutocompleteMatch(), 1210 instant->OnCancel(match != result().end() ? *match : AutocompleteMatch(),
1289 user_text_, 1211 user_text_,
1290 user_text_ + inline_autocomplete_text_); 1212 user_text_ + inline_autocomplete_text_);
1291 } 1213 }
1292 if (revert_popup) 1214 if (revert_popup)
1293 popup_->ResetToDefaultMatch(); 1215 popup_model()->ResetToDefaultMatch();
1294 view_->OnRevertTemporaryText(); 1216 view_->OnRevertTemporaryText();
1295 } 1217 }
1296 1218
1297 bool OmniboxEditModel::MaybeAcceptKeywordBySpace(const string16& new_text) { 1219 bool OmniboxEditModel::MaybeAcceptKeywordBySpace(const string16& new_text) {
1298 size_t keyword_length = new_text.length() - 1; 1220 size_t keyword_length = new_text.length() - 1;
1299 return (paste_state_ == NONE) && is_keyword_hint_ && !keyword_.empty() && 1221 return (paste_state_ == NONE) && is_keyword_hint_ && !keyword_.empty() &&
1300 inline_autocomplete_text_.empty() && 1222 inline_autocomplete_text_.empty() &&
1301 (keyword_.length() == keyword_length) && 1223 (keyword_.length() == keyword_length) &&
1302 IsSpaceCharForAcceptingKeyword(new_text[keyword_length]) && 1224 IsSpaceCharForAcceptingKeyword(new_text[keyword_length]) &&
1303 !new_text.compare(0, keyword_length, keyword_, 0, keyword_length) && 1225 !new_text.compare(0, keyword_length, keyword_, 0, keyword_length) &&
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1354 // Remove "?" if we're in forced query mode. 1276 // Remove "?" if we're in forced query mode.
1355 AutocompleteInput::RemoveForcedQueryStringIfNecessary( 1277 AutocompleteInput::RemoveForcedQueryStringIfNecessary(
1356 autocomplete_controller()->input().type(), &user_text); 1278 autocomplete_controller()->input().type(), &user_text);
1357 AutocompleteInput::RemoveForcedQueryStringIfNecessary( 1279 AutocompleteInput::RemoveForcedQueryStringIfNecessary(
1358 autocomplete_controller()->input().type(), &full_text); 1280 autocomplete_controller()->input().type(), &full_text);
1359 1281
1360 size_t start, end; 1282 size_t start, end;
1361 view_->GetSelectionBounds(&start, &end); 1283 view_->GetSelectionBounds(&start, &end);
1362 1284
1363 return instant->Update(match, user_text, full_text, start, end, 1285 return instant->Update(match, user_text, full_text, start, end,
1364 UseVerbatimInstant(), user_input_in_progress_, popup_->IsOpen(), 1286 UseVerbatimInstant(), user_input_in_progress_, popup_model()->IsOpen(),
1365 in_escape_handler_, KeywordIsSelected()); 1287 in_escape_handler_, KeywordIsSelected());
1366 } 1288 }
1367 1289
1368 void OmniboxEditModel::DoPreconnect(const AutocompleteMatch& match) {
1369 if (!match.destination_url.SchemeIs(extensions::kExtensionScheme)) {
1370 // Warm up DNS Prefetch cache, or preconnect to a search service.
1371 UMA_HISTOGRAM_ENUMERATION("Autocomplete.MatchType", match.type,
1372 AutocompleteMatch::NUM_TYPES);
1373 if (profile_->GetNetworkPredictor()) {
1374 profile_->GetNetworkPredictor()->AnticipateOmniboxUrl(
1375 match.destination_url,
1376 AutocompleteActionPredictor::IsPreconnectable(match));
1377 }
1378 // We could prefetch the alternate nav URL, if any, but because there
1379 // can be many of these as a user types an initial series of characters,
1380 // the OS DNS cache could suffer eviction problems for minimal gain.
1381 }
1382 }
1383
1384 // static 1290 // static
1385 bool OmniboxEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { 1291 bool OmniboxEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) {
1386 switch (c) { 1292 switch (c) {
1387 case 0x0020: // Space 1293 case 0x0020: // Space
1388 case 0x3000: // Ideographic Space 1294 case 0x3000: // Ideographic Space
1389 return true; 1295 return true;
1390 default: 1296 default:
1391 return false; 1297 return false;
1392 } 1298 }
1393 } 1299 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1425 instant->OmniboxFocusChanged(state, reason, NULL); 1331 instant->OmniboxFocusChanged(state, reason, NULL);
1426 1332
1427 // Update state and notify view if the omnibox has focus and the caret 1333 // Update state and notify view if the omnibox has focus and the caret
1428 // visibility changed. 1334 // visibility changed.
1429 const bool was_caret_visible = is_caret_visible(); 1335 const bool was_caret_visible = is_caret_visible();
1430 focus_state_ = state; 1336 focus_state_ = state;
1431 if (focus_state_ != OMNIBOX_FOCUS_NONE && 1337 if (focus_state_ != OMNIBOX_FOCUS_NONE &&
1432 is_caret_visible() != was_caret_visible) 1338 is_caret_visible() != was_caret_visible)
1433 view_->ApplyCaretVisibility(); 1339 view_->ApplyCaretVisibility();
1434 } 1340 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698