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

Side by Side Diff: components/omnibox/browser/omnibox_edit_model.cc

Issue 1855423003: Interpret '?' and Ctrl-K or Ctrl-E as putting omnibox in keyword search mode for Default Search Pro… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed unit test compilation Created 4 years, 7 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
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 "components/omnibox/browser/omnibox_edit_model.h" 5 #include "components/omnibox/browser/omnibox_edit_model.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 #include <utility> 9 #include <utility>
10 10
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 const char kOmniboxUserTextClearedHistogram[] = "Omnibox.UserTextCleared"; 64 const char kOmniboxUserTextClearedHistogram[] = "Omnibox.UserTextCleared";
65 65
66 enum UserTextClearedType { 66 enum UserTextClearedType {
67 OMNIBOX_USER_TEXT_CLEARED_BY_EDITING = 0, 67 OMNIBOX_USER_TEXT_CLEARED_BY_EDITING = 0,
68 OMNIBOX_USER_TEXT_CLEARED_WITH_ESCAPE = 1, 68 OMNIBOX_USER_TEXT_CLEARED_WITH_ESCAPE = 1,
69 OMNIBOX_USER_TEXT_CLEARED_NUM_OF_ITEMS, 69 OMNIBOX_USER_TEXT_CLEARED_NUM_OF_ITEMS,
70 }; 70 };
71 71
72 // Histogram name which counts the number of times the user enters 72 // Histogram name which counts the number of times the user enters
73 // keyword hint mode and via what method. The possible values are listed 73 // keyword hint mode and via what method. The possible values are listed
74 // in the EnteredKeywordModeMethod enum which is defined in the .h file. 74 // in the KeywordModeEntryMethod enum which is defined in the .h file.
75 const char kEnteredKeywordModeHistogram[] = "Omnibox.EnteredKeywordMode"; 75 const char kEnteredKeywordModeHistogram[] = "Omnibox.EnteredKeywordMode";
76 76
77 // Histogram name which counts the number of milliseconds a user takes 77 // Histogram name which counts the number of milliseconds a user takes
78 // between focusing and editing the omnibox. 78 // between focusing and editing the omnibox.
79 const char kFocusToEditTimeHistogram[] = "Omnibox.FocusToEditTime"; 79 const char kFocusToEditTimeHistogram[] = "Omnibox.FocusToEditTime";
80 80
81 // Histogram name which counts the number of milliseconds a user takes 81 // Histogram name which counts the number of milliseconds a user takes
82 // between focusing and opening an omnibox match. 82 // between focusing and opening an omnibox match.
83 const char kFocusToOpenTimeHistogram[] = "Omnibox.FocusToOpenTimeAnyPopupState"; 83 const char kFocusToOpenTimeHistogram[] = "Omnibox.FocusToOpenTimeAnyPopupState";
84 84
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 } // namespace 142 } // namespace
143 143
144 144
145 // OmniboxEditModel::State ---------------------------------------------------- 145 // OmniboxEditModel::State ----------------------------------------------------
146 146
147 OmniboxEditModel::State::State(bool user_input_in_progress, 147 OmniboxEditModel::State::State(bool user_input_in_progress,
148 const base::string16& user_text, 148 const base::string16& user_text,
149 const base::string16& gray_text, 149 const base::string16& gray_text,
150 const base::string16& keyword, 150 const base::string16& keyword,
151 bool is_keyword_hint, 151 bool is_keyword_hint,
152 KeywordModeEntryMethod keyword_mode_entry_method,
152 bool url_replacement_enabled, 153 bool url_replacement_enabled,
153 OmniboxFocusState focus_state, 154 OmniboxFocusState focus_state,
154 FocusSource focus_source, 155 FocusSource focus_source,
155 const AutocompleteInput& autocomplete_input) 156 const AutocompleteInput& autocomplete_input)
156 : user_input_in_progress(user_input_in_progress), 157 : user_input_in_progress(user_input_in_progress),
157 user_text(user_text), 158 user_text(user_text),
158 gray_text(gray_text), 159 gray_text(gray_text),
159 keyword(keyword), 160 keyword(keyword),
160 is_keyword_hint(is_keyword_hint), 161 is_keyword_hint(is_keyword_hint),
162 keyword_mode_entry_method(keyword_mode_entry_method),
161 url_replacement_enabled(url_replacement_enabled), 163 url_replacement_enabled(url_replacement_enabled),
162 focus_state(focus_state), 164 focus_state(focus_state),
163 focus_source(focus_source), 165 focus_source(focus_source),
164 autocomplete_input(autocomplete_input) { 166 autocomplete_input(autocomplete_input) {
165 } 167 }
166 168
167 OmniboxEditModel::State::State(const State& other) = default; 169 OmniboxEditModel::State::State(const State& other) = default;
168 170
169 OmniboxEditModel::State::~State() { 171 OmniboxEditModel::State::~State() {
170 } 172 }
171 173
172 174
173 // OmniboxEditModel ----------------------------------------------------------- 175 // OmniboxEditModel -----------------------------------------------------------
174 176
175 OmniboxEditModel::OmniboxEditModel(OmniboxView* view, 177 OmniboxEditModel::OmniboxEditModel(OmniboxView* view,
176 OmniboxEditController* controller, 178 OmniboxEditController* controller,
177 std::unique_ptr<OmniboxClient> client) 179 std::unique_ptr<OmniboxClient> client)
178 : client_(std::move(client)), 180 : client_(std::move(client)),
179 view_(view), 181 view_(view),
180 controller_(controller), 182 controller_(controller),
181 focus_state_(OMNIBOX_FOCUS_NONE), 183 focus_state_(OMNIBOX_FOCUS_NONE),
182 focus_source_(INVALID), 184 focus_source_(INVALID),
183 user_input_in_progress_(false), 185 user_input_in_progress_(false),
184 user_input_since_focus_(true), 186 user_input_since_focus_(true),
185 just_deleted_text_(false), 187 just_deleted_text_(false),
188 clearing_keyword_(false),
186 has_temporary_text_(false), 189 has_temporary_text_(false),
187 paste_state_(NONE), 190 paste_state_(NONE),
188 control_key_state_(UP), 191 control_key_state_(UP),
189 is_keyword_hint_(false), 192 is_keyword_hint_(false),
190 in_revert_(false), 193 in_revert_(false),
191 allow_exact_keyword_match_(false) { 194 allow_exact_keyword_match_(false) {
192 omnibox_controller_.reset(new OmniboxController(this, client_.get())); 195 omnibox_controller_.reset(new OmniboxController(this, client_.get()));
193 } 196 }
194 197
195 OmniboxEditModel::~OmniboxEditModel() { 198 OmniboxEditModel::~OmniboxEditModel() {
(...skipping 14 matching lines...) Expand all
210 view_->SelectAll(true); 213 view_->SelectAll(true);
211 } else { 214 } else {
212 InternalSetUserText(user_text); 215 InternalSetUserText(user_text);
213 } 216 }
214 } 217 }
215 218
216 UMA_HISTOGRAM_BOOLEAN("Omnibox.SaveStateForTabSwitch.UserInputInProgress", 219 UMA_HISTOGRAM_BOOLEAN("Omnibox.SaveStateForTabSwitch.UserInputInProgress",
217 user_input_in_progress_); 220 user_input_in_progress_);
218 return State( 221 return State(
219 user_input_in_progress_, user_text_, view_->GetGrayTextAutocompletion(), 222 user_input_in_progress_, user_text_, view_->GetGrayTextAutocompletion(),
220 keyword_, is_keyword_hint_, 223 keyword_, is_keyword_hint_, keyword_mode_entry_method_,
221 controller_->GetToolbarModel()->url_replacement_enabled(), 224 controller_->GetToolbarModel()->url_replacement_enabled(),
222 focus_state_, focus_source_, input_); 225 focus_state_, focus_source_, input_);
223 } 226 }
224 227
225 void OmniboxEditModel::RestoreState(const State* state) { 228 void OmniboxEditModel::RestoreState(const State* state) {
226 // We need to update the permanent text correctly and revert the view 229 // We need to update the permanent text correctly and revert the view
227 // regardless of whether there is saved state. 230 // regardless of whether there is saved state.
228 bool url_replacement_enabled = !state || state->url_replacement_enabled; 231 bool url_replacement_enabled = !state || state->url_replacement_enabled;
229 controller_->GetToolbarModel()->set_url_replacement_enabled( 232 controller_->GetToolbarModel()->set_url_replacement_enabled(
230 url_replacement_enabled); 233 url_replacement_enabled);
231 permanent_text_ = controller_->GetToolbarModel()->GetText(); 234 permanent_text_ = controller_->GetToolbarModel()->GetText();
232 // Don't muck with the search term replacement state, as we've just set it 235 // Don't muck with the search term replacement state, as we've just set it
233 // correctly. 236 // correctly.
234 view_->RevertWithoutResettingSearchTermReplacement(); 237 view_->RevertWithoutResettingSearchTermReplacement();
235 // Restore the autocomplete controller's input, or clear it if this is a new 238 // Restore the autocomplete controller's input, or clear it if this is a new
236 // tab. 239 // tab.
237 input_ = state ? state->autocomplete_input : AutocompleteInput(); 240 input_ = state ? state->autocomplete_input : AutocompleteInput();
238 if (!state) 241 if (!state)
239 return; 242 return;
240 243
241 SetFocusState(state->focus_state, OMNIBOX_FOCUS_CHANGE_TAB_SWITCH); 244 SetFocusState(state->focus_state, OMNIBOX_FOCUS_CHANGE_TAB_SWITCH);
242 focus_source_ = state->focus_source; 245 focus_source_ = state->focus_source;
243 // Restore any user editing. 246 // Restore any user editing.
244 if (state->user_input_in_progress) { 247 if (state->user_input_in_progress) {
245 // NOTE: Be sure and set keyword-related state BEFORE invoking 248 // NOTE: Be sure and set keyword-related state BEFORE invoking
246 // DisplayTextFromUserText(), as its result depends upon this state. 249 // DisplayTextFromUserText(), as its result depends upon this state.
247 keyword_ = state->keyword; 250 keyword_ = state->keyword;
248 is_keyword_hint_ = state->is_keyword_hint; 251 is_keyword_hint_ = state->is_keyword_hint;
252 keyword_mode_entry_method_ = state->keyword_mode_entry_method;
249 view_->SetUserText(state->user_text, 253 view_->SetUserText(state->user_text,
250 DisplayTextFromUserText(state->user_text), false); 254 DisplayTextFromUserText(state->user_text), false);
251 view_->SetGrayTextAutocompletion(state->gray_text); 255 view_->SetGrayTextAutocompletion(state->gray_text);
252 } 256 }
253 } 257 }
254 258
255 AutocompleteMatch OmniboxEditModel::CurrentMatch( 259 AutocompleteMatch OmniboxEditModel::CurrentMatch(
256 GURL* alternate_nav_url) const { 260 GURL* alternate_nav_url) const {
257 // If we have a valid match use it. Otherwise get one for the current text. 261 // If we have a valid match use it. Otherwise get one for the current text.
258 AutocompleteMatch match = omnibox_controller_->current_match(); 262 AutocompleteMatch match = omnibox_controller_->current_match();
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 325
322 const base::string16 final_text = view_->GetText() + suggestion; 326 const base::string16 final_text = view_->GetText() + suggestion;
323 view_->OnBeforePossibleChange(); 327 view_->OnBeforePossibleChange();
324 view_->SetWindowTextAndCaretPos(final_text, final_text.length(), false, 328 view_->SetWindowTextAndCaretPos(final_text, final_text.length(), false,
325 false); 329 false);
326 view_->OnAfterPossibleChange(true); 330 view_->OnAfterPossibleChange(true);
327 return true; 331 return true;
328 } 332 }
329 333
330 void OmniboxEditModel::OnChanged() { 334 void OmniboxEditModel::OnChanged() {
335 // If the user input a "?", put them into keyword mode.
336 if (!clearing_keyword_ && !just_deleted_text_ &&
337 user_text_ == base::ASCIIToUTF16("?")) {
338 user_text_ = base::string16();
339 EnterKeywordModeForDefaultSearchProvider(
340 KeywordModeEntryMethod::QUESTION_MARK);
341 }
342
331 // Hide any suggestions we might be showing. 343 // Hide any suggestions we might be showing.
332 view_->SetGrayTextAutocompletion(base::string16()); 344 view_->SetGrayTextAutocompletion(base::string16());
333 345
334 // Don't call CurrentMatch() when there's no editing, as in this case we'll 346 // Don't call CurrentMatch() when there's no editing, as in this case we'll
335 // never actually use it. This avoids running the autocomplete providers (and 347 // never actually use it. This avoids running the autocomplete providers (and
336 // any systems they then spin up) during startup. 348 // any systems they then spin up) during startup.
337 const AutocompleteMatch& current_match = user_input_in_progress_ ? 349 const AutocompleteMatch& current_match = user_input_in_progress_ ?
338 CurrentMatch(NULL) : AutocompleteMatch(); 350 CurrentMatch(NULL) : AutocompleteMatch();
339 351
340 client_->OnTextChanged(current_match, user_input_in_progress_, user_text_, 352 client_->OnTextChanged(current_match, user_input_in_progress_, user_text_,
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 match.transition = ui::PAGE_TRANSITION_LINK; 630 match.transition = ui::PAGE_TRANSITION_LINK;
619 } 631 }
620 632
621 client_->OnInputAccepted(match); 633 client_->OnInputAccepted(match);
622 634
623 DCHECK(popup_model()); 635 DCHECK(popup_model());
624 view_->OpenMatch(match, disposition, alternate_nav_url, base::string16(), 636 view_->OpenMatch(match, disposition, alternate_nav_url, base::string16(),
625 popup_model()->selected_line()); 637 popup_model()->selected_line());
626 } 638 }
627 639
640 void OmniboxEditModel::EnterKeywordModeForDefaultSearchProvider(
641 KeywordModeEntryMethod keyword_mode_entry_method) {
642 autocomplete_controller()->Stop(false);
643
644 view_->OnBeforePossibleChange();
645
646 base::string16 query = DisplayTextFromUserText(user_text_);
Peter Kasting 2016/04/28 21:24:41 Nit: Can be const
Tom (Use chromium acct) 2016/04/29 01:10:21 Done.
647 keyword_ = client_->GetTemplateURLService()->
648 GetDefaultSearchProvider()->keyword();
649 is_keyword_hint_ = false;
650 keyword_mode_entry_method_ = keyword_mode_entry_method;
651 view_->SetUserText(keyword_ + base::ASCIIToUTF16(" ") + query, query, true);
652
653 view_->OnAfterPossibleChange(false);
654
655 UMA_HISTOGRAM_ENUMERATION(kEnteredKeywordModeHistogram,
656 (int)keyword_mode_entry_method,
Peter Kasting 2016/04/28 21:24:41 Nit: No C-style casts (several places)
Tom (Use chromium acct) 2016/04/29 01:10:21 Done.
657 (int)KeywordModeEntryMethod::NUM_ITEMS);
658 }
659
628 void OmniboxEditModel::OpenMatch(AutocompleteMatch match, 660 void OmniboxEditModel::OpenMatch(AutocompleteMatch match,
629 WindowOpenDisposition disposition, 661 WindowOpenDisposition disposition,
630 const GURL& alternate_nav_url, 662 const GURL& alternate_nav_url,
631 const base::string16& pasted_text, 663 const base::string16& pasted_text,
632 size_t index) { 664 size_t index) {
633 const base::TimeTicks& now(base::TimeTicks::Now()); 665 const base::TimeTicks& now(base::TimeTicks::Now());
634 base::TimeDelta elapsed_time_since_user_first_modified_omnibox( 666 base::TimeDelta elapsed_time_since_user_first_modified_omnibox(
635 now - time_user_first_modified_omnibox_); 667 now - time_user_first_modified_omnibox_);
636 autocomplete_controller()->UpdateMatchDestinationURLWithQueryFormulationTime( 668 autocomplete_controller()->UpdateMatchDestinationURLWithQueryFormulationTime(
637 elapsed_time_since_user_first_modified_omnibox, &match); 669 elapsed_time_since_user_first_modified_omnibox, &match);
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
776 match.transition | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)); 808 match.transition | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR));
777 if (observer && observer->HasSeenPendingLoad()) 809 if (observer && observer->HasSeenPendingLoad())
778 ignore_result(observer.release()); // The observer will delete itself. 810 ignore_result(observer.release()); // The observer will delete itself.
779 } 811 }
780 812
781 BookmarkModel* bookmark_model = client_->GetBookmarkModel(); 813 BookmarkModel* bookmark_model = client_->GetBookmarkModel();
782 if (bookmark_model && bookmark_model->IsBookmarked(match.destination_url)) 814 if (bookmark_model && bookmark_model->IsBookmarked(match.destination_url))
783 client_->OnBookmarkLaunched(); 815 client_->OnBookmarkLaunched();
784 } 816 }
785 817
786 bool OmniboxEditModel::AcceptKeyword(EnteredKeywordModeMethod entered_method) { 818 bool OmniboxEditModel::AcceptKeyword(
819 KeywordModeEntryMethod keyword_mode_entry_method) {
787 DCHECK(is_keyword_hint_ && !keyword_.empty()); 820 DCHECK(is_keyword_hint_ && !keyword_.empty());
788 821
789 autocomplete_controller()->Stop(false); 822 autocomplete_controller()->Stop(false);
790 is_keyword_hint_ = false; 823 is_keyword_hint_ = false;
824 keyword_mode_entry_method_ = keyword_mode_entry_method;
791 825
792 if (popup_model() && popup_model()->IsOpen()) 826 if (popup_model() && popup_model()->IsOpen())
793 popup_model()->SetSelectedLineState(OmniboxPopupModel::KEYWORD); 827 popup_model()->SetSelectedLineState(OmniboxPopupModel::KEYWORD);
794 else 828 else
795 StartAutocomplete(false, true, true); 829 StartAutocomplete(false, true, true);
796 830
797 // When entering keyword mode via tab, the new text to show is whatever the 831 // When entering keyword mode via tab, the new text to show is whatever the
798 // newly-selected match in the dropdown is. When entering via space, however, 832 // newly-selected match in the dropdown is. When entering via space, however,
799 // we should make sure to use the actual |user_text_| as the basis for the new 833 // we should make sure to use the actual |user_text_| as the basis for the new
800 // text. This ensures that if the user types "<keyword><space>" and the 834 // text. This ensures that if the user types "<keyword><space>" and the
801 // default match would have inline autocompleted a further string (e.g. 835 // default match would have inline autocompleted a further string (e.g.
802 // because there's a past multi-word search beginning with this keyword), the 836 // because there's a past multi-word search beginning with this keyword), the
803 // inline autocompletion doesn't get filled in as the keyword search query 837 // inline autocompletion doesn't get filled in as the keyword search query
804 // text. 838 // text.
805 // 839 //
806 // We also treat tabbing into keyword mode like tabbing through the popup in 840 // We also treat tabbing into keyword mode like tabbing through the popup in
807 // that we set |has_temporary_text_|, whereas pressing space is treated like 841 // that we set |has_temporary_text_|, whereas pressing space is treated like
808 // a new keystroke that changes the current match instead of overlaying it 842 // a new keystroke that changes the current match instead of overlaying it
809 // with a temporary one. This is important because rerunning autocomplete 843 // with a temporary one. This is important because rerunning autocomplete
810 // after the user pressed space, which will have happened just before reaching 844 // after the user pressed space, which will have happened just before reaching
811 // here, may have generated a new match, which the user won't actually see and 845 // here, may have generated a new match, which the user won't actually see and
812 // which we don't want to switch back to when existing keyword mode; see 846 // which we don't want to switch back to when existing keyword mode; see
813 // comments in ClearKeyword(). 847 // comments in ClearKeyword().
814 if (entered_method == ENTERED_KEYWORD_MODE_VIA_TAB) { 848 if (keyword_mode_entry_method == KeywordModeEntryMethod::TAB) {
815 // Ensure the current selection is saved before showing keyword mode 849 // Ensure the current selection is saved before showing keyword mode
816 // so that moving to another line and then reverting the text will restore 850 // so that moving to another line and then reverting the text will restore
817 // the current state properly. 851 // the current state properly.
818 bool save_original_selection = !has_temporary_text_; 852 bool save_original_selection = !has_temporary_text_;
819 has_temporary_text_ = true; 853 has_temporary_text_ = true;
820 const AutocompleteMatch& match = CurrentMatch(NULL); 854 const AutocompleteMatch& match = CurrentMatch(NULL);
821 original_url_ = match.destination_url; 855 original_url_ = match.destination_url;
822 view_->OnTemporaryTextMaybeChanged( 856 view_->OnTemporaryTextMaybeChanged(
823 DisplayTextFromUserText(match.fill_into_edit), 857 DisplayTextFromUserText(match.fill_into_edit),
824 save_original_selection, true); 858 save_original_selection, true);
825 } else { 859 } else {
826 view_->OnTemporaryTextMaybeChanged(DisplayTextFromUserText(user_text_), 860 view_->OnTemporaryTextMaybeChanged(DisplayTextFromUserText(user_text_),
827 false, true); 861 false, true);
828 } 862 }
829 863
830 base::RecordAction(base::UserMetricsAction("AcceptedKeywordHint")); 864 base::RecordAction(base::UserMetricsAction("AcceptedKeywordHint"));
831 UMA_HISTOGRAM_ENUMERATION(kEnteredKeywordModeHistogram, entered_method, 865 UMA_HISTOGRAM_ENUMERATION(kEnteredKeywordModeHistogram,
832 ENTERED_KEYWORD_MODE_NUM_ITEMS); 866 (int)keyword_mode_entry_method,
867 (int)KeywordModeEntryMethod::NUM_ITEMS);
833 868
834 return true; 869 return true;
835 } 870 }
836 871
837 void OmniboxEditModel::AcceptTemporaryTextAsUserText() { 872 void OmniboxEditModel::AcceptTemporaryTextAsUserText() {
838 InternalSetUserText(UserTextFromDisplayText(view_->GetText())); 873 InternalSetUserText(UserTextFromDisplayText(view_->GetText()));
839 has_temporary_text_ = false; 874 has_temporary_text_ = false;
840 875
841 if (user_input_in_progress_ || !in_revert_) 876 if (user_input_in_progress_ || !in_revert_)
842 client_->OnInputStateChanged(); 877 client_->OnInputStateChanged();
843 } 878 }
844 879
845 void OmniboxEditModel::ClearKeyword() { 880 void OmniboxEditModel::ClearKeyword() {
846 autocomplete_controller()->Stop(false); 881 autocomplete_controller()->Stop(false);
882 base::AutoReset<bool> reset_cleared_keyword(&clearing_keyword_, true);
847 883
848 // While we're always in keyword mode upon reaching here, sometimes we've just 884 // While we're always in keyword mode upon reaching here, sometimes we've just
849 // toggled in via space or tab, and sometimes we're on a non-toggled line 885 // toggled in via space or tab, and sometimes we're on a non-toggled line
850 // (usually because the user has typed a search string). Keep track of the 886 // (usually because the user has typed a search string). Keep track of the
851 // difference, as we'll need it below. 887 // difference, as we'll need it below.
852 bool was_toggled_into_keyword_mode = 888 bool was_toggled_into_keyword_mode =
853 popup_model()->selected_line_state() == OmniboxPopupModel::KEYWORD; 889 popup_model()->selected_line_state() == OmniboxPopupModel::KEYWORD;
854 890
855 omnibox_controller_->ClearPopupKeywordMode(); 891 omnibox_controller_->ClearPopupKeywordMode();
856 892
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
892 // inline-autocompletable search "x y", then typing "x" will inline- 928 // inline-autocompletable search "x y", then typing "x" will inline-
893 // autocomplete to "xyz.com", hitting space will toggle into keyword mode, but 929 // autocomplete to "xyz.com", hitting space will toggle into keyword mode, but
894 // then hitting backspace could wind up with the default match as the "x y" 930 // then hitting backspace could wind up with the default match as the "x y"
895 // search, which feels bizarre. 931 // search, which feels bizarre.
896 if (was_toggled_into_keyword_mode && has_temporary_text_) { 932 if (was_toggled_into_keyword_mode && has_temporary_text_) {
897 // State 4 above. 933 // State 4 above.
898 is_keyword_hint_ = true; 934 is_keyword_hint_ = true;
899 const base::string16 window_text = keyword_ + view_->GetText(); 935 const base::string16 window_text = keyword_ + view_->GetText();
900 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(), 936 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length(),
901 false, true); 937 false, true);
938
939 // If the user has typed "goo<tab>", then backspace, they will be left with
940 // "google.com" in the omnibox with no text selected. The user text is
941 // still "goo", so odd behavior can result if we don't sync the user text
942 // to the new display text.
943 AcceptTemporaryTextAsUserText();
Peter Kasting 2016/04/28 21:24:41 I don't think this is right. If I have an entry i
Tom (Use chromium acct) 2016/04/29 01:10:21 To repro the odd behavior (without the call to Acc
Peter Kasting 2016/04/29 01:36:47 Ensure the keyword mode you're tabbing into is not
902 } else { 944 } else {
903 // States 1-3 above. 945 // States 1-3 above.
904 view_->OnBeforePossibleChange(); 946 view_->OnBeforePossibleChange();
905 // Add a space after the keyword to allow the user to continue typing 947 // Add a space after the keyword to allow the user to continue typing
906 // without re-enabling keyword mode. The common case is state 3, where 948 // without re-enabling keyword mode. The common case is state 3, where
907 // the user entered keyword mode unintentionally, so backspacing 949 // the user entered keyword mode unintentionally, so backspacing
908 // immediately out of keyword mode should keep the space. In states 1 and 950 // immediately out of keyword mode should keep the space. In states 1 and
909 // 2, having the space is "safer" behavior. For instance, if the user types 951 // 2, having the space is "safer" behavior. For instance, if the user types
910 // "google.com f" or "google.com<tab>f" in the omnibox, moves the cursor to 952 // "google.com f" or "google.com<tab>f" in the omnibox, moves the cursor to
911 // the left, and presses backspace to leave keyword mode (state 1), it's 953 // the left, and presses backspace to leave keyword mode (state 1), it's
912 // better to have the space because it may be what the user wanted. The 954 // better to have the space because it may be what the user wanted. The
913 // user can easily delete it. On the other hand, if there is no space and 955 // user can easily delete it. On the other hand, if there is no space and
914 // the user wants it, it's more work to add because typing the space will 956 // the user wants it, it's more work to add because typing the space will
915 // enter keyword mode, which then the user would have to leave again. 957 // enter keyword mode, which then the user would have to leave again.
916 const base::string16 window_text = 958
917 keyword_ + base::ASCIIToUTF16(" ") + view_->GetText(); 959 // If we entered keyword mode in a special way like using a keyboard
918 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length() + 1, 960 // shortcut or typing a question mark in a blank omnibox, don't restore the
919 false, false); 961 // keyword. Instead, restore the question mark iff the user originally
962 // typed one.
963 base::string16 prefix;
964 if (keyword_mode_entry_method_ == KeywordModeEntryMethod::QUESTION_MARK)
965 prefix = base::ASCIIToUTF16("?");
966 else if (keyword_mode_entry_method_ !=
967 KeywordModeEntryMethod::KEYBOARD_SHORTCUT)
968 prefix = keyword_ + base::ASCIIToUTF16(" ");
969
920 keyword_.clear(); 970 keyword_.clear();
921 is_keyword_hint_ = false; 971 is_keyword_hint_ = false;
972
973 view_->SetUserText(prefix + view_->GetText());
974 view_->SetCaretPos(prefix.length());
Peter Kasting 2016/04/28 21:24:41 Why call these and not SetWindowTextAndCaretPos()?
Tom (Use chromium acct) 2016/04/29 01:10:21 If I use SetWidnowTextAndCaretPos, I get this beha
Peter Kasting 2016/04/29 01:36:47 That doesn't sound like the right cause; this code
975
922 view_->OnAfterPossibleChange(false); 976 view_->OnAfterPossibleChange(false);
977 StartAutocomplete(false, true, false);
Peter Kasting 2016/04/28 21:24:41 Why is this needed? SetUserText() above should ha
Tom (Use chromium acct) 2016/04/29 01:10:21 Done.
923 } 978 }
924 } 979 }
925 980
926 void OmniboxEditModel::OnSetFocus(bool control_down) { 981 void OmniboxEditModel::OnSetFocus(bool control_down) {
927 last_omnibox_focus_ = base::TimeTicks::Now(); 982 last_omnibox_focus_ = base::TimeTicks::Now();
928 user_input_since_focus_ = false; 983 user_input_since_focus_ = false;
929 984
930 // If the omnibox lost focus while the caret was hidden and then regained 985 // If the omnibox lost focus while the caret was hidden and then regained
931 // focus, OnSetFocus() is called and should restore visibility. Note that 986 // focus, OnSetFocus() is called and should restore visibility. Note that
932 // focus can be regained without an accompanying call to 987 // focus can be regained without an accompanying call to
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
1148 if (call_controller_onchanged) 1203 if (call_controller_onchanged)
1149 OnChanged(); 1204 OnChanged();
1150 } 1205 }
1151 1206
1152 bool OmniboxEditModel::OnAfterPossibleChange(const base::string16& old_text, 1207 bool OmniboxEditModel::OnAfterPossibleChange(const base::string16& old_text,
1153 const base::string16& new_text, 1208 const base::string16& new_text,
1154 size_t selection_start, 1209 size_t selection_start,
1155 size_t selection_end, 1210 size_t selection_end,
1156 bool selection_differs, 1211 bool selection_differs,
1157 bool text_differs, 1212 bool text_differs,
1213 bool keyword_differs,
1158 bool just_deleted_text, 1214 bool just_deleted_text,
1159 bool allow_keyword_ui_change) { 1215 bool allow_keyword_ui_change) {
1160 // Update the paste state as appropriate: if we're just finishing a paste 1216 // Update the paste state as appropriate: if we're just finishing a paste
1161 // that replaced all the text, preserve that information; otherwise, if we've 1217 // that replaced all the text, preserve that information; otherwise, if we've
1162 // made some other edit, clear paste tracking. 1218 // made some other edit, clear paste tracking.
1163 if (paste_state_ == PASTING) 1219 if (paste_state_ == PASTING)
1164 paste_state_ = PASTED; 1220 paste_state_ = PASTED;
1165 else if (text_differs) 1221 else if (text_differs)
1166 paste_state_ = NONE; 1222 paste_state_ = NONE;
1167 1223
(...skipping 19 matching lines...) Expand all
1187 const bool user_text_changed = 1243 const bool user_text_changed =
1188 text_differs || (selection_differs && !inline_autocomplete_text_.empty()); 1244 text_differs || (selection_differs && !inline_autocomplete_text_.empty());
1189 1245
1190 // If something has changed while the control key is down, prevent 1246 // If something has changed while the control key is down, prevent
1191 // "ctrl-enter" until the control key is released. 1247 // "ctrl-enter" until the control key is released.
1192 if ((text_differs || selection_differs) && 1248 if ((text_differs || selection_differs) &&
1193 (control_key_state_ == DOWN_WITHOUT_CHANGE)) 1249 (control_key_state_ == DOWN_WITHOUT_CHANGE))
1194 control_key_state_ = DOWN_WITH_CHANGE; 1250 control_key_state_ = DOWN_WITH_CHANGE;
1195 1251
1196 if (!user_text_changed) 1252 if (!user_text_changed)
1197 return false; 1253 return keyword_differs;
1198 1254
1199 // If the user text has not changed, we do not want to change the model's 1255 // If the user text has not changed, we do not want to change the model's
1200 // state associated with the text. Otherwise, we can get surprising behavior 1256 // state associated with the text. Otherwise, we can get surprising behavior
1201 // where the autocompleted text unexpectedly reappears, e.g. crbug.com/55983 1257 // where the autocompleted text unexpectedly reappears, e.g. crbug.com/55983
1202 InternalSetUserText(UserTextFromDisplayText(new_text)); 1258 InternalSetUserText(UserTextFromDisplayText(new_text));
1203 has_temporary_text_ = false; 1259 has_temporary_text_ = false;
1204 1260
1205 // Track when the user has deleted text so we won't allow inline 1261 // Track when the user has deleted text so we won't allow inline
1206 // autocomplete. 1262 // autocomplete.
1207 just_deleted_text_ = just_deleted_text; 1263 just_deleted_text_ = just_deleted_text;
(...skipping 14 matching lines...) Expand all
1222 // if the user hit space in mid-string after a keyword. 1278 // if the user hit space in mid-string after a keyword.
1223 // |allow_exact_keyword_match_| will be used by StartAutocomplete() method, 1279 // |allow_exact_keyword_match_| will be used by StartAutocomplete() method,
1224 // which will be called by |view_->UpdatePopup()|; so after that returns we 1280 // which will be called by |view_->UpdatePopup()|; so after that returns we
1225 // can safely reset this flag. 1281 // can safely reset this flag.
1226 allow_exact_keyword_match_ = text_differs && allow_keyword_ui_change && 1282 allow_exact_keyword_match_ = text_differs && allow_keyword_ui_change &&
1227 !just_deleted_text && no_selection && 1283 !just_deleted_text && no_selection &&
1228 CreatedKeywordSearchByInsertingSpaceInMiddle(old_text, user_text_, 1284 CreatedKeywordSearchByInsertingSpaceInMiddle(old_text, user_text_,
1229 selection_start); 1285 selection_start);
1230 view_->UpdatePopup(); 1286 view_->UpdatePopup();
1231 if (allow_exact_keyword_match_) { 1287 if (allow_exact_keyword_match_) {
1288 keyword_mode_entry_method_ = KeywordModeEntryMethod::SPACE_IN_MIDDLE;
1232 UMA_HISTOGRAM_ENUMERATION(kEnteredKeywordModeHistogram, 1289 UMA_HISTOGRAM_ENUMERATION(kEnteredKeywordModeHistogram,
1233 ENTERED_KEYWORD_MODE_VIA_SPACE_IN_MIDDLE, 1290 (int)KeywordModeEntryMethod::SPACE_IN_MIDDLE,
1234 ENTERED_KEYWORD_MODE_NUM_ITEMS); 1291 (int)KeywordModeEntryMethod::NUM_ITEMS);
1235 allow_exact_keyword_match_ = false; 1292 allow_exact_keyword_match_ = false;
1236 } 1293 }
1237 1294
1238 // Change to keyword mode if the user is now pressing space after a keyword 1295 // Change to keyword mode if the user is now pressing space after a keyword
1239 // name. Note that if this is the case, then even if there was no keyword 1296 // name. Note that if this is the case, then even if there was no keyword
1240 // hint when we entered this function (e.g. if the user has used space to 1297 // hint when we entered this function (e.g. if the user has used space to
1241 // replace some selected text that was adjoined to this keyword), there will 1298 // replace some selected text that was adjoined to this keyword), there will
1242 // be one now because of the call to UpdatePopup() above; so it's safe for 1299 // be one now because of the call to UpdatePopup() above; so it's safe for
1243 // MaybeAcceptKeywordBySpace() to look at |keyword_| and |is_keyword_hint_| to 1300 // MaybeAcceptKeywordBySpace() to look at |keyword_| and |is_keyword_hint_| to
1244 // determine what keyword, if any, is applicable. 1301 // determine what keyword, if any, is applicable.
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
1369 view_->OnRevertTemporaryText(); 1426 view_->OnRevertTemporaryText();
1370 } 1427 }
1371 1428
1372 bool OmniboxEditModel::MaybeAcceptKeywordBySpace( 1429 bool OmniboxEditModel::MaybeAcceptKeywordBySpace(
1373 const base::string16& new_text) { 1430 const base::string16& new_text) {
1374 size_t keyword_length = new_text.length() - 1; 1431 size_t keyword_length = new_text.length() - 1;
1375 return (paste_state_ == NONE) && is_keyword_hint_ && 1432 return (paste_state_ == NONE) && is_keyword_hint_ &&
1376 (keyword_.length() == keyword_length) && 1433 (keyword_.length() == keyword_length) &&
1377 IsSpaceCharForAcceptingKeyword(new_text[keyword_length]) && 1434 IsSpaceCharForAcceptingKeyword(new_text[keyword_length]) &&
1378 !new_text.compare(0, keyword_length, keyword_, 0, keyword_length) && 1435 !new_text.compare(0, keyword_length, keyword_, 0, keyword_length) &&
1379 AcceptKeyword(ENTERED_KEYWORD_MODE_VIA_SPACE_AT_END); 1436 AcceptKeyword(KeywordModeEntryMethod::SPACE_AT_END);
1380 } 1437 }
1381 1438
1382 bool OmniboxEditModel::CreatedKeywordSearchByInsertingSpaceInMiddle( 1439 bool OmniboxEditModel::CreatedKeywordSearchByInsertingSpaceInMiddle(
1383 const base::string16& old_text, 1440 const base::string16& old_text,
1384 const base::string16& new_text, 1441 const base::string16& new_text,
1385 size_t caret_position) const { 1442 size_t caret_position) const {
1386 DCHECK_GE(new_text.length(), caret_position); 1443 DCHECK_GE(new_text.length(), caret_position);
1387 1444
1388 // Check simple conditions first. 1445 // Check simple conditions first.
1389 if ((paste_state_ != NONE) || (caret_position < 2) || 1446 if ((paste_state_ != NONE) || (caret_position < 2) ||
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1463 // Update state and notify view if the omnibox has focus and the caret 1520 // Update state and notify view if the omnibox has focus and the caret
1464 // visibility changed. 1521 // visibility changed.
1465 const bool was_caret_visible = is_caret_visible(); 1522 const bool was_caret_visible = is_caret_visible();
1466 focus_state_ = state; 1523 focus_state_ = state;
1467 if (focus_state_ != OMNIBOX_FOCUS_NONE && 1524 if (focus_state_ != OMNIBOX_FOCUS_NONE &&
1468 is_caret_visible() != was_caret_visible) 1525 is_caret_visible() != was_caret_visible)
1469 view_->ApplyCaretVisibility(); 1526 view_->ApplyCaretVisibility();
1470 1527
1471 client_->OnFocusChanged(focus_state_, reason); 1528 client_->OnFocusChanged(focus_state_, reason);
1472 } 1529 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698