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_edit.h" | 5 #include "chrome/browser/autocomplete/autocomplete_edit.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 has_temporary_text_ = false; | 166 has_temporary_text_ = false; |
167 } | 167 } |
168 | 168 |
169 void AutocompleteEditModel::FinalizeInstantQuery( | 169 void AutocompleteEditModel::FinalizeInstantQuery( |
170 const string16& input_text, | 170 const string16& input_text, |
171 const string16& suggest_text, | 171 const string16& suggest_text, |
172 bool skip_inline_autocomplete) { | 172 bool skip_inline_autocomplete) { |
173 if (skip_inline_autocomplete) { | 173 if (skip_inline_autocomplete) { |
174 const string16 final_text = input_text + suggest_text; | 174 const string16 final_text = input_text + suggest_text; |
175 view_->OnBeforePossibleChange(); | 175 view_->OnBeforePossibleChange(); |
176 view_->SetWindowTextAndCaretPos(final_text, final_text.length()); | 176 view_->SetWindowTextAndCaretPos(final_text, final_text.length(), false, |
| 177 false); |
177 view_->OnAfterPossibleChange(); | 178 view_->OnAfterPossibleChange(); |
178 } else if (popup_->IsOpen()) { | 179 } else if (popup_->IsOpen()) { |
179 SearchProvider* search_provider = | 180 SearchProvider* search_provider = |
180 autocomplete_controller_->search_provider(); | 181 autocomplete_controller_->search_provider(); |
181 // There may be no providers during testing; guard against that. | 182 // There may be no providers during testing; guard against that. |
182 if (search_provider) | 183 if (search_provider) |
183 search_provider->FinalizeInstantQuery(input_text, suggest_text); | 184 search_provider->FinalizeInstantQuery(input_text, suggest_text); |
184 } | 185 } |
185 } | 186 } |
186 | 187 |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 } | 400 } |
400 | 401 |
401 void AutocompleteEditModel::Revert() { | 402 void AutocompleteEditModel::Revert() { |
402 SetInputInProgress(false); | 403 SetInputInProgress(false); |
403 paste_state_ = NONE; | 404 paste_state_ = NONE; |
404 InternalSetUserText(string16()); | 405 InternalSetUserText(string16()); |
405 keyword_.clear(); | 406 keyword_.clear(); |
406 is_keyword_hint_ = false; | 407 is_keyword_hint_ = false; |
407 has_temporary_text_ = false; | 408 has_temporary_text_ = false; |
408 view_->SetWindowTextAndCaretPos(permanent_text_, | 409 view_->SetWindowTextAndCaretPos(permanent_text_, |
409 has_focus_ ? permanent_text_.length() : 0); | 410 has_focus_ ? permanent_text_.length() : 0, |
| 411 false, true); |
410 NetworkActionPredictor* network_action_predictor = | 412 NetworkActionPredictor* network_action_predictor = |
411 NetworkActionPredictorFactory::GetForProfile(profile_); | 413 NetworkActionPredictorFactory::GetForProfile(profile_); |
412 if (network_action_predictor) | 414 if (network_action_predictor) |
413 network_action_predictor->ClearTransitionalMatches(); | 415 network_action_predictor->ClearTransitionalMatches(); |
414 } | 416 } |
415 | 417 |
416 void AutocompleteEditModel::StartAutocomplete( | 418 void AutocompleteEditModel::StartAutocomplete( |
417 bool has_selected_text, | 419 bool has_selected_text, |
418 bool prevent_inline_autocomplete) const { | 420 bool prevent_inline_autocomplete) const { |
| 421 ClearPopupKeywordMode(); |
| 422 |
419 bool keyword_is_selected = KeywordIsSelected(); | 423 bool keyword_is_selected = KeywordIsSelected(); |
420 popup_->SetHoveredLine(AutocompletePopupModel::kNoMatch); | 424 popup_->SetHoveredLine(AutocompletePopupModel::kNoMatch); |
421 // We don't explicitly clear AutocompletePopupModel::manually_selected_match, | 425 // We don't explicitly clear AutocompletePopupModel::manually_selected_match, |
422 // as Start ends up invoking AutocompletePopupModel::OnResultChanged which | 426 // as Start ends up invoking AutocompletePopupModel::OnResultChanged which |
423 // clears it. | 427 // clears it. |
424 autocomplete_controller_->Start( | 428 autocomplete_controller_->Start( |
425 user_text_, GetDesiredTLD(), | 429 user_text_, GetDesiredTLD(), |
426 prevent_inline_autocomplete || just_deleted_text_ || | 430 prevent_inline_autocomplete || just_deleted_text_ || |
427 (has_selected_text && inline_autocomplete_text_.empty()) || | 431 (has_selected_text && inline_autocomplete_text_.empty()) || |
428 (paste_state_ != NONE), keyword_is_selected, | 432 (paste_state_ != NONE), keyword_is_selected, |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
620 | 624 |
621 InstantController* instant = controller_->GetInstant(); | 625 InstantController* instant = controller_->GetInstant(); |
622 if (instant && !popup_->IsOpen()) | 626 if (instant && !popup_->IsOpen()) |
623 instant->DestroyPreviewContents(); | 627 instant->DestroyPreviewContents(); |
624 in_revert_ = false; | 628 in_revert_ = false; |
625 } | 629 } |
626 | 630 |
627 bool AutocompleteEditModel::AcceptKeyword() { | 631 bool AutocompleteEditModel::AcceptKeyword() { |
628 DCHECK(is_keyword_hint_ && !keyword_.empty()); | 632 DCHECK(is_keyword_hint_ && !keyword_.empty()); |
629 | 633 |
630 view_->OnBeforePossibleChange(); | 634 autocomplete_controller_->Stop(false); |
631 view_->SetWindowTextAndCaretPos(string16(), 0); | |
632 is_keyword_hint_ = false; | 635 is_keyword_hint_ = false; |
633 view_->OnAfterPossibleChange(); | 636 |
634 just_deleted_text_ = false; // OnAfterPossibleChange() erroneously sets this | 637 if (popup_->IsOpen()) |
635 // since the edit contents have disappeared. It | 638 popup_->SetSelectedLineState(AutocompletePopupModel::KEYWORD); |
636 // doesn't really matter, but we clear it to be | 639 else |
637 // consistent. | 640 StartAutocomplete(false, true); |
| 641 |
| 642 // Ensure the current selection is saved before showing keyword mode |
| 643 // so that moving to another line and then reverting the text will restore |
| 644 // the current state properly. |
| 645 view_->OnTemporaryTextMaybeChanged( |
| 646 DisplayTextFromUserText(CurrentMatch().fill_into_edit), |
| 647 !has_temporary_text_); |
| 648 has_temporary_text_ = true; |
| 649 |
638 content::RecordAction(UserMetricsAction("AcceptedKeywordHint")); | 650 content::RecordAction(UserMetricsAction("AcceptedKeywordHint")); |
639 return true; | 651 return true; |
640 } | 652 } |
641 | 653 |
642 void AutocompleteEditModel::ClearKeyword(const string16& visible_text) { | 654 void AutocompleteEditModel::ClearKeyword(const string16& visible_text) { |
643 view_->OnBeforePossibleChange(); | 655 autocomplete_controller_->Stop(false); |
| 656 ClearPopupKeywordMode(); |
| 657 |
644 const string16 window_text(keyword_ + visible_text); | 658 const string16 window_text(keyword_ + visible_text); |
645 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length()); | 659 |
646 keyword_.clear(); | 660 // Only reset the result if the edit text has changed since the |
647 is_keyword_hint_ = false; | 661 // keyword was accepted, or if the popup is closed. |
648 view_->OnAfterPossibleChange(); | 662 if (just_deleted_text_ || !visible_text.empty() || !popup_->IsOpen()) { |
649 just_deleted_text_ = true; // OnAfterPossibleChange() fails to clear this | 663 view_->OnBeforePossibleChange(); |
650 // since the edit contents have actually grown | 664 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(), |
651 // longer. | 665 false, false); |
| 666 keyword_.clear(); |
| 667 is_keyword_hint_ = false; |
| 668 view_->OnAfterPossibleChange(); |
| 669 just_deleted_text_ = true; // OnAfterPossibleChange() fails to clear this |
| 670 // since the edit contents have actually grown |
| 671 // longer. |
| 672 } else { |
| 673 is_keyword_hint_ = true; |
| 674 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(), |
| 675 false, true); |
| 676 } |
652 } | 677 } |
653 | 678 |
654 const AutocompleteResult& AutocompleteEditModel::result() const { | 679 const AutocompleteResult& AutocompleteEditModel::result() const { |
655 return autocomplete_controller_->result(); | 680 return autocomplete_controller_->result(); |
656 } | 681 } |
657 | 682 |
658 void AutocompleteEditModel::OnSetFocus(bool control_down) { | 683 void AutocompleteEditModel::OnSetFocus(bool control_down) { |
659 has_focus_ = true; | 684 has_focus_ = true; |
660 control_key_state_ = control_down ? DOWN_WITHOUT_CHANGE : UP; | 685 control_key_state_ = control_down ? DOWN_WITHOUT_CHANGE : UP; |
661 | 686 |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
904 match->fill_into_edit.substr(match->inline_autocomplete_offset); | 929 match->fill_into_edit.substr(match->inline_autocomplete_offset); |
905 } | 930 } |
906 | 931 |
907 if (!prerender::IsOmniboxEnabled(profile_)) | 932 if (!prerender::IsOmniboxEnabled(profile_)) |
908 DoPreconnect(*match); | 933 DoPreconnect(*match); |
909 | 934 |
910 // We could prefetch the alternate nav URL, if any, but because there | 935 // We could prefetch the alternate nav URL, if any, but because there |
911 // can be many of these as a user types an initial series of characters, | 936 // can be many of these as a user types an initial series of characters, |
912 // the OS DNS cache could suffer eviction problems for minimal gain. | 937 // the OS DNS cache could suffer eviction problems for minimal gain. |
913 | 938 |
914 is_keyword_hint = popup_->GetKeywordForMatch(*match, &keyword); | 939 is_keyword_hint = match->GetKeyword(&keyword); |
915 } | 940 } |
| 941 |
916 popup_->OnResultChanged(); | 942 popup_->OnResultChanged(); |
917 OnPopupDataChanged(inline_autocomplete_text, NULL, keyword, | 943 OnPopupDataChanged(inline_autocomplete_text, NULL, keyword, |
918 is_keyword_hint); | 944 is_keyword_hint); |
919 } else { | 945 } else { |
920 popup_->OnResultChanged(); | 946 popup_->OnResultChanged(); |
921 } | 947 } |
922 | 948 |
923 if (popup_->IsOpen()) { | 949 if (popup_->IsOpen()) { |
924 PopupBoundsChangedTo(popup_->view()->GetTargetBounds()); | 950 PopupBoundsChangedTo(popup_->view()->GetTargetBounds()); |
925 } else if (was_open) { | 951 } else if (was_open) { |
(...skipping 12 matching lines...) Expand all Loading... |
938 void AutocompleteEditModel::InternalSetUserText(const string16& text) { | 964 void AutocompleteEditModel::InternalSetUserText(const string16& text) { |
939 user_text_ = text; | 965 user_text_ = text; |
940 just_deleted_text_ = false; | 966 just_deleted_text_ = false; |
941 inline_autocomplete_text_.clear(); | 967 inline_autocomplete_text_.clear(); |
942 } | 968 } |
943 | 969 |
944 bool AutocompleteEditModel::KeywordIsSelected() const { | 970 bool AutocompleteEditModel::KeywordIsSelected() const { |
945 return !is_keyword_hint_ && !keyword_.empty(); | 971 return !is_keyword_hint_ && !keyword_.empty(); |
946 } | 972 } |
947 | 973 |
| 974 void AutocompleteEditModel::ClearPopupKeywordMode() const { |
| 975 if (popup_->IsOpen() && |
| 976 popup_->selected_line_state() == AutocompletePopupModel::KEYWORD) |
| 977 popup_->SetSelectedLineState(AutocompletePopupModel::NORMAL); |
| 978 } |
| 979 |
948 string16 AutocompleteEditModel::DisplayTextFromUserText( | 980 string16 AutocompleteEditModel::DisplayTextFromUserText( |
949 const string16& text) const { | 981 const string16& text) const { |
950 return KeywordIsSelected() ? | 982 return KeywordIsSelected() ? |
951 KeywordProvider::SplitReplacementStringFromInput(text, false) : text; | 983 KeywordProvider::SplitReplacementStringFromInput(text, false) : text; |
952 } | 984 } |
953 | 985 |
954 string16 AutocompleteEditModel::UserTextFromDisplayText( | 986 string16 AutocompleteEditModel::UserTextFromDisplayText( |
955 const string16& text) const { | 987 const string16& text) const { |
956 return KeywordIsSelected() ? (keyword_ + char16(' ') + text) : text; | 988 return KeywordIsSelected() ? (keyword_ + char16(' ') + text) : text; |
957 } | 989 } |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1037 old_user_text.length() - caret_position + 1)) { | 1069 old_user_text.length() - caret_position + 1)) { |
1038 return false; | 1070 return false; |
1039 } | 1071 } |
1040 | 1072 |
1041 // Then check if the text before the inserted space matches a keyword. | 1073 // Then check if the text before the inserted space matches a keyword. |
1042 string16 keyword; | 1074 string16 keyword; |
1043 TrimWhitespace(new_user_text.substr(0, caret_position - 1), | 1075 TrimWhitespace(new_user_text.substr(0, caret_position - 1), |
1044 TRIM_LEADING, &keyword); | 1076 TRIM_LEADING, &keyword); |
1045 | 1077 |
1046 // Only allow exact keyword match if |keyword| represents a keyword hint. | 1078 // Only allow exact keyword match if |keyword| represents a keyword hint. |
1047 return keyword.length() && popup_->GetKeywordForText(keyword, &keyword); | 1079 return keyword.length() && |
| 1080 !autocomplete_controller_->keyword_provider()-> |
| 1081 GetKeywordForText(keyword).empty(); |
1048 } | 1082 } |
1049 | 1083 |
1050 bool AutocompleteEditModel::DoInstant(const AutocompleteMatch& match, | 1084 bool AutocompleteEditModel::DoInstant(const AutocompleteMatch& match, |
1051 string16* suggested_text) { | 1085 string16* suggested_text) { |
1052 DCHECK(suggested_text); | 1086 DCHECK(suggested_text); |
1053 | 1087 |
1054 if (in_revert_) | 1088 if (in_revert_) |
1055 return false; | 1089 return false; |
1056 | 1090 |
1057 InstantController* instant = controller_->GetInstant(); | 1091 InstantController* instant = controller_->GetInstant(); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1113 // static | 1147 // static |
1114 bool AutocompleteEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { | 1148 bool AutocompleteEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { |
1115 switch (c) { | 1149 switch (c) { |
1116 case 0x0020: // Space | 1150 case 0x0020: // Space |
1117 case 0x3000: // Ideographic Space | 1151 case 0x3000: // Ideographic Space |
1118 return true; | 1152 return true; |
1119 default: | 1153 default: |
1120 return false; | 1154 return false; |
1121 } | 1155 } |
1122 } | 1156 } |
OLD | NEW |