OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |