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 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 has_temporary_text_ = false; | 165 has_temporary_text_ = false; |
166 } | 166 } |
167 | 167 |
168 void AutocompleteEditModel::FinalizeInstantQuery( | 168 void AutocompleteEditModel::FinalizeInstantQuery( |
169 const string16& input_text, | 169 const string16& input_text, |
170 const string16& suggest_text, | 170 const string16& suggest_text, |
171 bool skip_inline_autocomplete) { | 171 bool skip_inline_autocomplete) { |
172 if (skip_inline_autocomplete) { | 172 if (skip_inline_autocomplete) { |
173 const string16 final_text = input_text + suggest_text; | 173 const string16 final_text = input_text + suggest_text; |
174 view_->OnBeforePossibleChange(); | 174 view_->OnBeforePossibleChange(); |
175 view_->SetWindowTextAndCaretPos(final_text, final_text.length()); | 175 view_->SetWindowTextAndCaretPos(final_text, final_text.length(), false, |
| 176 false); |
176 view_->OnAfterPossibleChange(); | 177 view_->OnAfterPossibleChange(); |
177 } else if (popup_->IsOpen()) { | 178 } else if (popup_->IsOpen()) { |
178 SearchProvider* search_provider = | 179 SearchProvider* search_provider = |
179 autocomplete_controller_->search_provider(); | 180 autocomplete_controller_->search_provider(); |
180 // There may be no providers during testing; guard against that. | 181 // There may be no providers during testing; guard against that. |
181 if (search_provider) | 182 if (search_provider) |
182 search_provider->FinalizeInstantQuery(input_text, suggest_text); | 183 search_provider->FinalizeInstantQuery(input_text, suggest_text); |
183 } | 184 } |
184 } | 185 } |
185 | 186 |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 } | 397 } |
397 | 398 |
398 void AutocompleteEditModel::Revert() { | 399 void AutocompleteEditModel::Revert() { |
399 SetInputInProgress(false); | 400 SetInputInProgress(false); |
400 paste_state_ = NONE; | 401 paste_state_ = NONE; |
401 InternalSetUserText(string16()); | 402 InternalSetUserText(string16()); |
402 keyword_.clear(); | 403 keyword_.clear(); |
403 is_keyword_hint_ = false; | 404 is_keyword_hint_ = false; |
404 has_temporary_text_ = false; | 405 has_temporary_text_ = false; |
405 view_->SetWindowTextAndCaretPos(permanent_text_, | 406 view_->SetWindowTextAndCaretPos(permanent_text_, |
406 has_focus_ ? permanent_text_.length() : 0); | 407 has_focus_ ? permanent_text_.length() : 0, |
| 408 false, true); |
407 NetworkActionPredictor* network_action_predictor = | 409 NetworkActionPredictor* network_action_predictor = |
408 NetworkActionPredictorFactory::GetForProfile(profile_); | 410 NetworkActionPredictorFactory::GetForProfile(profile_); |
409 if (network_action_predictor) | 411 if (network_action_predictor) |
410 network_action_predictor->ClearTransitionalMatches(); | 412 network_action_predictor->ClearTransitionalMatches(); |
411 } | 413 } |
412 | 414 |
413 void AutocompleteEditModel::StartAutocomplete( | 415 void AutocompleteEditModel::StartAutocomplete( |
414 bool has_selected_text, | 416 bool has_selected_text, |
415 bool prevent_inline_autocomplete) const { | 417 bool prevent_inline_autocomplete) const { |
| 418 ClearPopupKeywordMode(); |
| 419 |
416 bool keyword_is_selected = KeywordIsSelected(); | 420 bool keyword_is_selected = KeywordIsSelected(); |
417 popup_->SetHoveredLine(AutocompletePopupModel::kNoMatch); | 421 popup_->SetHoveredLine(AutocompletePopupModel::kNoMatch); |
418 // We don't explicitly clear AutocompletePopupModel::manually_selected_match, | 422 // We don't explicitly clear AutocompletePopupModel::manually_selected_match, |
419 // as Start ends up invoking AutocompletePopupModel::OnResultChanged which | 423 // as Start ends up invoking AutocompletePopupModel::OnResultChanged which |
420 // clears it. | 424 // clears it. |
421 autocomplete_controller_->Start( | 425 autocomplete_controller_->Start( |
422 user_text_, GetDesiredTLD(), | 426 user_text_, GetDesiredTLD(), |
423 prevent_inline_autocomplete || just_deleted_text_ || | 427 prevent_inline_autocomplete || just_deleted_text_ || |
424 (has_selected_text && inline_autocomplete_text_.empty()) || | 428 (has_selected_text && inline_autocomplete_text_.empty()) || |
425 (paste_state_ != NONE), keyword_is_selected, | 429 (paste_state_ != NONE), keyword_is_selected, |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 | 607 |
604 InstantController* instant = controller_->GetInstant(); | 608 InstantController* instant = controller_->GetInstant(); |
605 if (instant && !popup_->IsOpen()) | 609 if (instant && !popup_->IsOpen()) |
606 instant->DestroyPreviewContents(); | 610 instant->DestroyPreviewContents(); |
607 in_revert_ = false; | 611 in_revert_ = false; |
608 } | 612 } |
609 | 613 |
610 bool AutocompleteEditModel::AcceptKeyword() { | 614 bool AutocompleteEditModel::AcceptKeyword() { |
611 DCHECK(is_keyword_hint_ && !keyword_.empty()); | 615 DCHECK(is_keyword_hint_ && !keyword_.empty()); |
612 | 616 |
613 view_->OnBeforePossibleChange(); | 617 autocomplete_controller_->Stop(false); |
614 view_->SetWindowTextAndCaretPos(string16(), 0); | |
615 is_keyword_hint_ = false; | 618 is_keyword_hint_ = false; |
616 view_->OnAfterPossibleChange(); | 619 |
617 just_deleted_text_ = false; // OnAfterPossibleChange() erroneously sets this | 620 if (popup_->IsOpen()) |
618 // since the edit contents have disappeared. It | 621 popup_->SetSelectedLineState(AutocompletePopupModel::KEYWORD); |
619 // doesn't really matter, but we clear it to be | 622 else |
620 // consistent. | 623 StartAutocomplete(false, true); |
| 624 |
| 625 // Ensure the current selection is saved before showing keyword mode |
| 626 // so that moving to another line and then reverting the text will restore |
| 627 // the current state properly. |
| 628 view_->OnTemporaryTextMaybeChanged( |
| 629 DisplayTextFromUserText(CurrentMatch().fill_into_edit), |
| 630 !has_temporary_text_); |
| 631 has_temporary_text_ = true; |
| 632 |
621 content::RecordAction(UserMetricsAction("AcceptedKeywordHint")); | 633 content::RecordAction(UserMetricsAction("AcceptedKeywordHint")); |
622 return true; | 634 return true; |
623 } | 635 } |
624 | 636 |
625 void AutocompleteEditModel::ClearKeyword(const string16& visible_text) { | 637 void AutocompleteEditModel::ClearKeyword(const string16& visible_text) { |
626 view_->OnBeforePossibleChange(); | 638 autocomplete_controller_->Stop(false); |
| 639 ClearPopupKeywordMode(); |
| 640 |
627 const string16 window_text(keyword_ + visible_text); | 641 const string16 window_text(keyword_ + visible_text); |
628 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length()); | 642 |
629 keyword_.clear(); | 643 // Only reset the result if the edit text has changed since the |
630 is_keyword_hint_ = false; | 644 // keyword was accepted, or if the popup is closed. |
631 view_->OnAfterPossibleChange(); | 645 if (just_deleted_text_ || !visible_text.empty() || !popup_->IsOpen()) { |
632 just_deleted_text_ = true; // OnAfterPossibleChange() fails to clear this | 646 view_->OnBeforePossibleChange(); |
633 // since the edit contents have actually grown | 647 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(), |
634 // longer. | 648 false, false); |
| 649 keyword_.clear(); |
| 650 is_keyword_hint_ = false; |
| 651 view_->OnAfterPossibleChange(); |
| 652 just_deleted_text_ = true; // OnAfterPossibleChange() fails to clear this |
| 653 // since the edit contents have actually grown |
| 654 // longer. |
| 655 } else { |
| 656 is_keyword_hint_ = true; |
| 657 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(), |
| 658 false, true); |
| 659 } |
635 } | 660 } |
636 | 661 |
637 const AutocompleteResult& AutocompleteEditModel::result() const { | 662 const AutocompleteResult& AutocompleteEditModel::result() const { |
638 return autocomplete_controller_->result(); | 663 return autocomplete_controller_->result(); |
639 } | 664 } |
640 | 665 |
641 void AutocompleteEditModel::OnSetFocus(bool control_down) { | 666 void AutocompleteEditModel::OnSetFocus(bool control_down) { |
642 has_focus_ = true; | 667 has_focus_ = true; |
643 control_key_state_ = control_down ? DOWN_WITHOUT_CHANGE : UP; | 668 control_key_state_ = control_down ? DOWN_WITHOUT_CHANGE : UP; |
644 | 669 |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
887 match->fill_into_edit.substr(match->inline_autocomplete_offset); | 912 match->fill_into_edit.substr(match->inline_autocomplete_offset); |
888 } | 913 } |
889 | 914 |
890 if (!prerender::IsOmniboxEnabled(profile_)) | 915 if (!prerender::IsOmniboxEnabled(profile_)) |
891 DoPreconnect(*match); | 916 DoPreconnect(*match); |
892 | 917 |
893 // We could prefetch the alternate nav URL, if any, but because there | 918 // We could prefetch the alternate nav URL, if any, but because there |
894 // can be many of these as a user types an initial series of characters, | 919 // can be many of these as a user types an initial series of characters, |
895 // the OS DNS cache could suffer eviction problems for minimal gain. | 920 // the OS DNS cache could suffer eviction problems for minimal gain. |
896 | 921 |
897 is_keyword_hint = popup_->GetKeywordForMatch(*match, &keyword); | 922 is_keyword_hint = match->GetKeyword(&keyword); |
898 } | 923 } |
| 924 |
899 popup_->OnResultChanged(); | 925 popup_->OnResultChanged(); |
900 OnPopupDataChanged(inline_autocomplete_text, NULL, keyword, | 926 OnPopupDataChanged(inline_autocomplete_text, NULL, keyword, |
901 is_keyword_hint); | 927 is_keyword_hint); |
902 } else { | 928 } else { |
903 popup_->OnResultChanged(); | 929 popup_->OnResultChanged(); |
904 } | 930 } |
905 | 931 |
906 if (popup_->IsOpen()) { | 932 if (popup_->IsOpen()) { |
907 PopupBoundsChangedTo(popup_->view()->GetTargetBounds()); | 933 PopupBoundsChangedTo(popup_->view()->GetTargetBounds()); |
908 } else if (was_open) { | 934 } else if (was_open) { |
(...skipping 12 matching lines...) Expand all Loading... |
921 void AutocompleteEditModel::InternalSetUserText(const string16& text) { | 947 void AutocompleteEditModel::InternalSetUserText(const string16& text) { |
922 user_text_ = text; | 948 user_text_ = text; |
923 just_deleted_text_ = false; | 949 just_deleted_text_ = false; |
924 inline_autocomplete_text_.clear(); | 950 inline_autocomplete_text_.clear(); |
925 } | 951 } |
926 | 952 |
927 bool AutocompleteEditModel::KeywordIsSelected() const { | 953 bool AutocompleteEditModel::KeywordIsSelected() const { |
928 return !is_keyword_hint_ && !keyword_.empty(); | 954 return !is_keyword_hint_ && !keyword_.empty(); |
929 } | 955 } |
930 | 956 |
| 957 void AutocompleteEditModel::ClearPopupKeywordMode() const { |
| 958 if (popup_->IsOpen() && |
| 959 popup_->selected_line_state() == AutocompletePopupModel::KEYWORD) |
| 960 popup_->SetSelectedLineState(AutocompletePopupModel::NORMAL); |
| 961 } |
| 962 |
931 string16 AutocompleteEditModel::DisplayTextFromUserText( | 963 string16 AutocompleteEditModel::DisplayTextFromUserText( |
932 const string16& text) const { | 964 const string16& text) const { |
933 return KeywordIsSelected() ? | 965 return KeywordIsSelected() ? |
934 KeywordProvider::SplitReplacementStringFromInput(text, false) : text; | 966 KeywordProvider::SplitReplacementStringFromInput(text, false) : text; |
935 } | 967 } |
936 | 968 |
937 string16 AutocompleteEditModel::UserTextFromDisplayText( | 969 string16 AutocompleteEditModel::UserTextFromDisplayText( |
938 const string16& text) const { | 970 const string16& text) const { |
939 return KeywordIsSelected() ? (keyword_ + char16(' ') + text) : text; | 971 return KeywordIsSelected() ? (keyword_ + char16(' ') + text) : text; |
940 } | 972 } |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1020 old_user_text.length() - caret_position + 1)) { | 1052 old_user_text.length() - caret_position + 1)) { |
1021 return false; | 1053 return false; |
1022 } | 1054 } |
1023 | 1055 |
1024 // Then check if the text before the inserted space matches a keyword. | 1056 // Then check if the text before the inserted space matches a keyword. |
1025 string16 keyword; | 1057 string16 keyword; |
1026 TrimWhitespace(new_user_text.substr(0, caret_position - 1), | 1058 TrimWhitespace(new_user_text.substr(0, caret_position - 1), |
1027 TRIM_LEADING, &keyword); | 1059 TRIM_LEADING, &keyword); |
1028 | 1060 |
1029 // Only allow exact keyword match if |keyword| represents a keyword hint. | 1061 // Only allow exact keyword match if |keyword| represents a keyword hint. |
1030 return keyword.length() && popup_->GetKeywordForText(keyword, &keyword); | 1062 return keyword.length() && |
| 1063 !autocomplete_controller_->keyword_provider()-> |
| 1064 GetKeywordForText(keyword).empty(); |
1031 } | 1065 } |
1032 | 1066 |
1033 bool AutocompleteEditModel::DoInstant(const AutocompleteMatch& match, | 1067 bool AutocompleteEditModel::DoInstant(const AutocompleteMatch& match, |
1034 string16* suggested_text) { | 1068 string16* suggested_text) { |
1035 DCHECK(suggested_text); | 1069 DCHECK(suggested_text); |
1036 | 1070 |
1037 if (in_revert_) | 1071 if (in_revert_) |
1038 return false; | 1072 return false; |
1039 | 1073 |
1040 InstantController* instant = controller_->GetInstant(); | 1074 InstantController* instant = controller_->GetInstant(); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1096 // static | 1130 // static |
1097 bool AutocompleteEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { | 1131 bool AutocompleteEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { |
1098 switch (c) { | 1132 switch (c) { |
1099 case 0x0020: // Space | 1133 case 0x0020: // Space |
1100 case 0x3000: // Ideographic Space | 1134 case 0x3000: // Ideographic Space |
1101 return true; | 1135 return true; |
1102 default: | 1136 default: |
1103 return false; | 1137 return false; |
1104 } | 1138 } |
1105 } | 1139 } |
OLD | NEW |