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

Side by Side Diff: chrome/browser/autocomplete/autocomplete_edit.cc

Issue 9570064: Fix keyword search erroneously not triggering in two obscure cases: (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 9 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 (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 814 matching lines...) Expand 10 before | Expand all | Expand 10 after
825 call_controller_onchanged = false; 825 call_controller_onchanged = false;
826 } 826 }
827 827
828 // We need to invoke OnChanged in case the destination url changed (as could 828 // We need to invoke OnChanged in case the destination url changed (as could
829 // happen when control is toggled). 829 // happen when control is toggled).
830 if (call_controller_onchanged) 830 if (call_controller_onchanged)
831 OnChanged(); 831 OnChanged();
832 } 832 }
833 833
834 bool AutocompleteEditModel::OnAfterPossibleChange( 834 bool AutocompleteEditModel::OnAfterPossibleChange(
835 const string16& old_text,
835 const string16& new_text, 836 const string16& new_text,
836 size_t selection_start, 837 size_t selection_start,
837 size_t selection_end, 838 size_t selection_end,
838 bool selection_differs, 839 bool selection_differs,
839 bool text_differs, 840 bool text_differs,
840 bool just_deleted_text, 841 bool just_deleted_text,
841 bool allow_keyword_ui_change) { 842 bool allow_keyword_ui_change) {
842 // Update the paste state as appropriate: if we're just finishing a paste 843 // Update the paste state as appropriate: if we're just finishing a paste
843 // that replaced all the text, preserve that information; otherwise, if we've 844 // that replaced all the text, preserve that information; otherwise, if we've
844 // made some other edit, clear paste tracking. 845 // made some other edit, clear paste tracking.
(...skipping 11 matching lines...) Expand all
856 // to update the popup if it's open, since the desired_tld will have changed. 857 // to update the popup if it's open, since the desired_tld will have changed.
857 if ((text_differs || selection_differs) && 858 if ((text_differs || selection_differs) &&
858 (control_key_state_ == DOWN_WITHOUT_CHANGE)) { 859 (control_key_state_ == DOWN_WITHOUT_CHANGE)) {
859 control_key_state_ = DOWN_WITH_CHANGE; 860 control_key_state_ = DOWN_WITH_CHANGE;
860 if (!text_differs && !popup_->IsOpen()) 861 if (!text_differs && !popup_->IsOpen())
861 return false; // Don't open the popup for no reason. 862 return false; // Don't open the popup for no reason.
862 } else if (!user_text_changed) { 863 } else if (!user_text_changed) {
863 return false; 864 return false;
864 } 865 }
865 866
866 const string16 old_user_text = user_text_;
867 // If the user text has not changed, we do not want to change the model's 867 // If the user text has not changed, we do not want to change the model's
868 // state associated with the text. Otherwise, we can get surprising behavior 868 // state associated with the text. Otherwise, we can get surprising behavior
869 // where the autocompleted text unexpectedly reappears, e.g. crbug.com/55983 869 // where the autocompleted text unexpectedly reappears, e.g. crbug.com/55983
870 if (user_text_changed) { 870 if (user_text_changed) {
871 InternalSetUserText(UserTextFromDisplayText(new_text)); 871 InternalSetUserText(UserTextFromDisplayText(new_text));
872 has_temporary_text_ = false; 872 has_temporary_text_ = false;
873 873
874 // Track when the user has deleted text so we won't allow inline 874 // Track when the user has deleted text so we won't allow inline
875 // autocomplete. 875 // autocomplete.
876 just_deleted_text_ = just_deleted_text; 876 just_deleted_text_ = just_deleted_text;
877 } 877 }
878 878
879 const bool no_selection = selection_start == selection_end; 879 const bool no_selection = selection_start == selection_end;
880 880
881 // Update the popup for the change, in the process changing to keyword mode 881 // Update the popup for the change, in the process changing to keyword mode
882 // if the user hit space in mid-string after a keyword. 882 // if the user hit space in mid-string after a keyword.
883 // |allow_exact_keyword_match_| will be used by StartAutocomplete() method, 883 // |allow_exact_keyword_match_| will be used by StartAutocomplete() method,
884 // which will be called by |view_->UpdatePopup()|. So we can safely clear 884 // which will be called by |view_->UpdatePopup()|; so after that returns we
885 // this flag afterwards. 885 // can safely reset this flag.
886 allow_exact_keyword_match_ = 886 allow_exact_keyword_match_ = text_differs && allow_keyword_ui_change &&
887 text_differs && allow_keyword_ui_change &&
888 !just_deleted_text && no_selection && 887 !just_deleted_text && no_selection &&
889 ShouldAllowExactKeywordMatch(old_user_text, user_text_, selection_start); 888 CreatedKeywordSearchByInsertingSpaceInMiddle(old_text, user_text_,
889 selection_start);
890 view_->UpdatePopup(); 890 view_->UpdatePopup();
891 allow_exact_keyword_match_ = false; 891 allow_exact_keyword_match_ = false;
892 892
893 // Change to keyword mode if the user has typed a keyword name and is now 893 // Change to keyword mode if the user is now pressing space after a keyword
894 // pressing space after the name. Accepting the keyword will update our 894 // name. Note that if this is the case, then even if there was no keyword
895 // state, so in that case there's no need to also return true here. 895 // hint when we entered this function (e.g. if the user has used space to
896 // replace some selected text that was adjoined to this keyword), there will
897 // be one now because of the call to UpdatePopup() above; so it's safe for
898 // MaybeAcceptKeywordBySpace() to look at |keyword_| and |is_keyword_hint_| to
899 // determine what keyword, if any, is applicable.
900 //
901 // If MaybeAcceptKeywordBySpace() accepts the keyword and returns true, that
902 // will have updated our state already, so in that case we don't also return
903 // true from this function.
896 return !(text_differs && allow_keyword_ui_change && !just_deleted_text && 904 return !(text_differs && allow_keyword_ui_change && !just_deleted_text &&
897 no_selection && selection_start == user_text_.length() && 905 no_selection && (selection_start == user_text_.length()) &&
898 MaybeAcceptKeywordBySpace(old_user_text, user_text_)); 906 MaybeAcceptKeywordBySpace(user_text_));
899 } 907 }
900 908
901 void AutocompleteEditModel::PopupBoundsChangedTo(const gfx::Rect& bounds) { 909 void AutocompleteEditModel::PopupBoundsChangedTo(const gfx::Rect& bounds) {
902 InstantController* instant = controller_->GetInstant(); 910 InstantController* instant = controller_->GetInstant();
903 if (instant) 911 if (instant)
904 instant->SetOmniboxBounds(bounds); 912 instant->SetOmniboxBounds(bounds);
905 } 913 }
906 914
907 void AutocompleteEditModel::OnResultChanged(bool default_match_changed) { 915 void AutocompleteEditModel::OnResultChanged(bool default_match_changed) {
908 const bool was_open = popup_->IsOpen(); 916 const bool was_open = popup_->IsOpen();
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1023 // text they typed and change back to the default item. 1031 // text they typed and change back to the default item.
1024 // NOTE: This purposefully does not reset paste_state_. 1032 // NOTE: This purposefully does not reset paste_state_.
1025 just_deleted_text_ = false; 1033 just_deleted_text_ = false;
1026 has_temporary_text_ = false; 1034 has_temporary_text_ = false;
1027 if (revert_popup) 1035 if (revert_popup)
1028 popup_->ResetToDefaultMatch(); 1036 popup_->ResetToDefaultMatch();
1029 view_->OnRevertTemporaryText(); 1037 view_->OnRevertTemporaryText();
1030 } 1038 }
1031 1039
1032 bool AutocompleteEditModel::MaybeAcceptKeywordBySpace( 1040 bool AutocompleteEditModel::MaybeAcceptKeywordBySpace(
1033 const string16& old_user_text, 1041 const string16& new_text) {
1034 const string16& new_user_text) { 1042 size_t keyword_length = new_text.length() - 1;
1035 return (paste_state_ == NONE) && is_keyword_hint_ && !keyword_.empty() && 1043 return (paste_state_ == NONE) && is_keyword_hint_ && !keyword_.empty() &&
1036 inline_autocomplete_text_.empty() && new_user_text.length() >= 2 && 1044 inline_autocomplete_text_.empty() &&
1037 IsSpaceCharForAcceptingKeyword(*new_user_text.rbegin()) && 1045 (keyword_.length() == keyword_length) &&
1038 !IsWhitespace(*(new_user_text.rbegin() + 1)) && 1046 IsSpaceCharForAcceptingKeyword(new_text[keyword_length]) &&
1039 (old_user_text.length() + 1 >= new_user_text.length()) && 1047 !new_text.compare(0, keyword_length, keyword_, 0, keyword_length) &&
1040 !new_user_text.compare(0, new_user_text.length() - 1, old_user_text,
1041 0, new_user_text.length() - 1) &&
1042 AcceptKeyword(); 1048 AcceptKeyword();
1043 } 1049 }
1044 1050
1045 bool AutocompleteEditModel::ShouldAllowExactKeywordMatch( 1051 bool AutocompleteEditModel::CreatedKeywordSearchByInsertingSpaceInMiddle(
1046 const string16& old_user_text, 1052 const string16& old_text,
1047 const string16& new_user_text, 1053 const string16& new_text,
1048 size_t caret_position) { 1054 size_t caret_position) const {
1055 DCHECK_GE(new_text.length(), caret_position);
1056
1049 // Check simple conditions first. 1057 // Check simple conditions first.
1050 if (paste_state_ != NONE || caret_position < 2 || 1058 if ((paste_state_ != NONE) || (caret_position < 2) ||
1051 new_user_text.length() <= caret_position || 1059 (old_text.length() < caret_position) ||
1052 old_user_text.length() < caret_position || 1060 (new_text.length() == caret_position))
1053 !IsSpaceCharForAcceptingKeyword(new_user_text[caret_position - 1]) || 1061 return false;
1054 IsSpaceCharForAcceptingKeyword(new_user_text[caret_position - 2]) || 1062 size_t space_position = caret_position - 1;
1055 new_user_text.compare(0, caret_position - 1, old_user_text, 1063 if (!IsSpaceCharForAcceptingKeyword(new_text[space_position]) ||
1056 0, caret_position - 1) || 1064 IsWhitespace(new_text[space_position - 1]) ||
1057 !new_user_text.compare(caret_position - 1, 1065 new_text.compare(0, space_position, old_text, 0, space_position) ||
1058 new_user_text.length() - caret_position + 1, 1066 !new_text.compare(space_position, new_text.length() - space_position,
1059 old_user_text, caret_position - 1, 1067 old_text, space_position,
1060 old_user_text.length() - caret_position + 1)) { 1068 old_text.length() - space_position)) {
1061 return false; 1069 return false;
1062 } 1070 }
1063 1071
1064 // Then check if the text before the inserted space matches a keyword. 1072 // Then check if the text before the inserted space matches a keyword.
1065 string16 keyword; 1073 string16 keyword;
1066 TrimWhitespace(new_user_text.substr(0, caret_position - 1), 1074 TrimWhitespace(new_text.substr(0, space_position), TRIM_LEADING, &keyword);
1067 TRIM_LEADING, &keyword); 1075 return !keyword.empty() &&
1068
1069 // Only allow exact keyword match if |keyword| represents a keyword hint.
1070 return keyword.length() &&
1071 !autocomplete_controller_->keyword_provider()-> 1076 !autocomplete_controller_->keyword_provider()->
1072 GetKeywordForText(keyword).empty(); 1077 GetKeywordForText(keyword).empty();
1073 } 1078 }
1074 1079
1075 bool AutocompleteEditModel::DoInstant(const AutocompleteMatch& match, 1080 bool AutocompleteEditModel::DoInstant(const AutocompleteMatch& match,
1076 string16* suggested_text) { 1081 string16* suggested_text) {
1077 DCHECK(suggested_text); 1082 DCHECK(suggested_text);
1078 1083
1079 if (in_revert_) 1084 if (in_revert_)
1080 return false; 1085 return false;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1138 // static 1143 // static
1139 bool AutocompleteEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { 1144 bool AutocompleteEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) {
1140 switch (c) { 1145 switch (c) {
1141 case 0x0020: // Space 1146 case 0x0020: // Space
1142 case 0x3000: // Ideographic Space 1147 case 0x3000: // Ideographic Space
1143 return true; 1148 return true;
1144 default: 1149 default:
1145 return false; 1150 return false;
1146 } 1151 }
1147 } 1152 }
OLDNEW
« no previous file with comments | « chrome/browser/autocomplete/autocomplete_edit.h ('k') | chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698