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 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 | 615 |
612 InstantController* instant = controller_->GetInstant(); | 616 InstantController* instant = controller_->GetInstant(); |
613 if (instant && !popup_->IsOpen()) | 617 if (instant && !popup_->IsOpen()) |
614 instant->DestroyPreviewContents(); | 618 instant->DestroyPreviewContents(); |
615 in_revert_ = false; | 619 in_revert_ = false; |
616 } | 620 } |
617 | 621 |
618 bool AutocompleteEditModel::AcceptKeyword() { | 622 bool AutocompleteEditModel::AcceptKeyword() { |
619 DCHECK(is_keyword_hint_ && !keyword_.empty()); | 623 DCHECK(is_keyword_hint_ && !keyword_.empty()); |
620 | 624 |
621 view_->OnBeforePossibleChange(); | 625 autocomplete_controller_->Stop(false); |
622 view_->SetWindowTextAndCaretPos(string16(), 0); | |
623 is_keyword_hint_ = false; | 626 is_keyword_hint_ = false; |
624 view_->OnAfterPossibleChange(); | 627 |
625 just_deleted_text_ = false; // OnAfterPossibleChange() erroneously sets this | 628 if (popup_->IsOpen()) |
626 // since the edit contents have disappeared. It | 629 popup_->SetSelectedLineState(AutocompletePopupModel::KEYWORD); |
627 // doesn't really matter, but we clear it to be | 630 else |
628 // consistent. | 631 StartAutocomplete(false, true); |
| 632 |
| 633 // Ensure the current selection is saved before showing keyword mode |
| 634 // so that moving to another line and then reverting the text will restore |
| 635 // the current state properly. |
| 636 view_->OnTemporaryTextMaybeChanged( |
| 637 DisplayTextFromUserText(CurrentMatch().fill_into_edit), |
| 638 !has_temporary_text_); |
| 639 has_temporary_text_ = true; |
| 640 |
629 content::RecordAction(UserMetricsAction("AcceptedKeywordHint")); | 641 content::RecordAction(UserMetricsAction("AcceptedKeywordHint")); |
630 return true; | 642 return true; |
631 } | 643 } |
632 | 644 |
633 void AutocompleteEditModel::ClearKeyword(const string16& visible_text) { | 645 void AutocompleteEditModel::ClearKeyword(const string16& visible_text) { |
634 view_->OnBeforePossibleChange(); | 646 autocomplete_controller_->Stop(false); |
| 647 ClearPopupKeywordMode(); |
| 648 |
635 const string16 window_text(keyword_ + visible_text); | 649 const string16 window_text(keyword_ + visible_text); |
636 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length()); | 650 |
637 keyword_.clear(); | 651 // Only reset the result if the edit text has changed since the |
638 is_keyword_hint_ = false; | 652 // keyword was accepted, or if the popup is closed. |
639 view_->OnAfterPossibleChange(); | 653 if (just_deleted_text_ || !visible_text.empty() || !popup_->IsOpen()) { |
640 just_deleted_text_ = true; // OnAfterPossibleChange() fails to clear this | 654 view_->OnBeforePossibleChange(); |
641 // since the edit contents have actually grown | 655 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(), |
642 // longer. | 656 false, false); |
| 657 keyword_.clear(); |
| 658 is_keyword_hint_ = false; |
| 659 view_->OnAfterPossibleChange(); |
| 660 just_deleted_text_ = true; // OnAfterPossibleChange() fails to clear this |
| 661 // since the edit contents have actually grown |
| 662 // longer. |
| 663 } else { |
| 664 is_keyword_hint_ = true; |
| 665 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(), |
| 666 false, true); |
| 667 } |
643 } | 668 } |
644 | 669 |
645 const AutocompleteResult& AutocompleteEditModel::result() const { | 670 const AutocompleteResult& AutocompleteEditModel::result() const { |
646 return autocomplete_controller_->result(); | 671 return autocomplete_controller_->result(); |
647 } | 672 } |
648 | 673 |
649 void AutocompleteEditModel::OnSetFocus(bool control_down) { | 674 void AutocompleteEditModel::OnSetFocus(bool control_down) { |
650 has_focus_ = true; | 675 has_focus_ = true; |
651 control_key_state_ = control_down ? DOWN_WITHOUT_CHANGE : UP; | 676 control_key_state_ = control_down ? DOWN_WITHOUT_CHANGE : UP; |
652 | 677 |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
895 match->fill_into_edit.substr(match->inline_autocomplete_offset); | 920 match->fill_into_edit.substr(match->inline_autocomplete_offset); |
896 } | 921 } |
897 | 922 |
898 if (!prerender::IsOmniboxEnabled(profile_)) | 923 if (!prerender::IsOmniboxEnabled(profile_)) |
899 DoPreconnect(*match); | 924 DoPreconnect(*match); |
900 | 925 |
901 // We could prefetch the alternate nav URL, if any, but because there | 926 // We could prefetch the alternate nav URL, if any, but because there |
902 // can be many of these as a user types an initial series of characters, | 927 // can be many of these as a user types an initial series of characters, |
903 // the OS DNS cache could suffer eviction problems for minimal gain. | 928 // the OS DNS cache could suffer eviction problems for minimal gain. |
904 | 929 |
905 is_keyword_hint = popup_->GetKeywordForMatch(*match, &keyword); | 930 is_keyword_hint = match->GetKeyword(&keyword); |
906 } | 931 } |
| 932 |
907 popup_->OnResultChanged(); | 933 popup_->OnResultChanged(); |
908 OnPopupDataChanged(inline_autocomplete_text, NULL, keyword, | 934 OnPopupDataChanged(inline_autocomplete_text, NULL, keyword, |
909 is_keyword_hint); | 935 is_keyword_hint); |
910 } else { | 936 } else { |
911 popup_->OnResultChanged(); | 937 popup_->OnResultChanged(); |
912 } | 938 } |
913 | 939 |
914 if (popup_->IsOpen()) { | 940 if (popup_->IsOpen()) { |
915 PopupBoundsChangedTo(popup_->view()->GetTargetBounds()); | 941 PopupBoundsChangedTo(popup_->view()->GetTargetBounds()); |
916 } else if (was_open) { | 942 } else if (was_open) { |
(...skipping 12 matching lines...) Expand all Loading... |
929 void AutocompleteEditModel::InternalSetUserText(const string16& text) { | 955 void AutocompleteEditModel::InternalSetUserText(const string16& text) { |
930 user_text_ = text; | 956 user_text_ = text; |
931 just_deleted_text_ = false; | 957 just_deleted_text_ = false; |
932 inline_autocomplete_text_.clear(); | 958 inline_autocomplete_text_.clear(); |
933 } | 959 } |
934 | 960 |
935 bool AutocompleteEditModel::KeywordIsSelected() const { | 961 bool AutocompleteEditModel::KeywordIsSelected() const { |
936 return !is_keyword_hint_ && !keyword_.empty(); | 962 return !is_keyword_hint_ && !keyword_.empty(); |
937 } | 963 } |
938 | 964 |
| 965 void AutocompleteEditModel::ClearPopupKeywordMode() const { |
| 966 if (popup_->IsOpen() && |
| 967 popup_->selected_line_state() == AutocompletePopupModel::KEYWORD) |
| 968 popup_->SetSelectedLineState(AutocompletePopupModel::NORMAL); |
| 969 } |
| 970 |
939 string16 AutocompleteEditModel::DisplayTextFromUserText( | 971 string16 AutocompleteEditModel::DisplayTextFromUserText( |
940 const string16& text) const { | 972 const string16& text) const { |
941 return KeywordIsSelected() ? | 973 return KeywordIsSelected() ? |
942 KeywordProvider::SplitReplacementStringFromInput(text, false) : text; | 974 KeywordProvider::SplitReplacementStringFromInput(text, false) : text; |
943 } | 975 } |
944 | 976 |
945 string16 AutocompleteEditModel::UserTextFromDisplayText( | 977 string16 AutocompleteEditModel::UserTextFromDisplayText( |
946 const string16& text) const { | 978 const string16& text) const { |
947 return KeywordIsSelected() ? (keyword_ + char16(' ') + text) : text; | 979 return KeywordIsSelected() ? (keyword_ + char16(' ') + text) : text; |
948 } | 980 } |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1028 old_user_text.length() - caret_position + 1)) { | 1060 old_user_text.length() - caret_position + 1)) { |
1029 return false; | 1061 return false; |
1030 } | 1062 } |
1031 | 1063 |
1032 // Then check if the text before the inserted space matches a keyword. | 1064 // Then check if the text before the inserted space matches a keyword. |
1033 string16 keyword; | 1065 string16 keyword; |
1034 TrimWhitespace(new_user_text.substr(0, caret_position - 1), | 1066 TrimWhitespace(new_user_text.substr(0, caret_position - 1), |
1035 TRIM_LEADING, &keyword); | 1067 TRIM_LEADING, &keyword); |
1036 | 1068 |
1037 // Only allow exact keyword match if |keyword| represents a keyword hint. | 1069 // Only allow exact keyword match if |keyword| represents a keyword hint. |
1038 return keyword.length() && popup_->GetKeywordForText(keyword, &keyword); | 1070 return keyword.length() && |
| 1071 !autocomplete_controller_->keyword_provider()-> |
| 1072 GetKeywordForText(keyword).empty(); |
1039 } | 1073 } |
1040 | 1074 |
1041 bool AutocompleteEditModel::DoInstant(const AutocompleteMatch& match, | 1075 bool AutocompleteEditModel::DoInstant(const AutocompleteMatch& match, |
1042 string16* suggested_text) { | 1076 string16* suggested_text) { |
1043 DCHECK(suggested_text); | 1077 DCHECK(suggested_text); |
1044 | 1078 |
1045 if (in_revert_) | 1079 if (in_revert_) |
1046 return false; | 1080 return false; |
1047 | 1081 |
1048 InstantController* instant = controller_->GetInstant(); | 1082 InstantController* instant = controller_->GetInstant(); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1104 // static | 1138 // static |
1105 bool AutocompleteEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { | 1139 bool AutocompleteEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { |
1106 switch (c) { | 1140 switch (c) { |
1107 case 0x0020: // Space | 1141 case 0x0020: // Space |
1108 case 0x3000: // Ideographic Space | 1142 case 0x3000: // Ideographic Space |
1109 return true; | 1143 return true; |
1110 default: | 1144 default: |
1111 return false; | 1145 return false; |
1112 } | 1146 } |
1113 } | 1147 } |
OLD | NEW |