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/ui/omnibox/omnibox_edit_model.h" | 5 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 controller_(controller), | 88 controller_(controller), |
89 has_focus_(false), | 89 has_focus_(false), |
90 user_input_in_progress_(false), | 90 user_input_in_progress_(false), |
91 just_deleted_text_(false), | 91 just_deleted_text_(false), |
92 has_temporary_text_(false), | 92 has_temporary_text_(false), |
93 paste_state_(NONE), | 93 paste_state_(NONE), |
94 control_key_state_(UP), | 94 control_key_state_(UP), |
95 is_keyword_hint_(false), | 95 is_keyword_hint_(false), |
96 profile_(profile), | 96 profile_(profile), |
97 in_revert_(false), | 97 in_revert_(false), |
98 allow_exact_keyword_match_(false), | 98 allow_exact_keyword_match_(false) { |
99 instant_complete_behavior_(INSTANT_COMPLETE_DELAYED) { | |
100 } | 99 } |
101 | 100 |
102 OmniboxEditModel::~OmniboxEditModel() { | 101 OmniboxEditModel::~OmniboxEditModel() { |
103 } | 102 } |
104 | 103 |
105 const OmniboxEditModel::State OmniboxEditModel::GetStateForTabSwitch() { | 104 const OmniboxEditModel::State OmniboxEditModel::GetStateForTabSwitch() { |
106 // Like typing, switching tabs "accepts" the temporary text as the user | 105 // Like typing, switching tabs "accepts" the temporary text as the user |
107 // text, because it makes little sense to have temporary text when the | 106 // text, because it makes little sense to have temporary text when the |
108 // popup is closed. | 107 // popup is closed. |
109 if (user_input_in_progress_) { | 108 if (user_input_in_progress_) { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 SearchProvider* search_provider = | 176 SearchProvider* search_provider = |
178 autocomplete_controller_->search_provider(); | 177 autocomplete_controller_->search_provider(); |
179 // There may be no providers during testing; guard against that. | 178 // There may be no providers during testing; guard against that. |
180 if (search_provider) | 179 if (search_provider) |
181 search_provider->FinalizeInstantQuery(input_text, suggest_text); | 180 search_provider->FinalizeInstantQuery(input_text, suggest_text); |
182 } | 181 } |
183 } | 182 } |
184 | 183 |
185 void OmniboxEditModel::SetSuggestedText(const string16& text, | 184 void OmniboxEditModel::SetSuggestedText(const string16& text, |
186 InstantCompleteBehavior behavior) { | 185 InstantCompleteBehavior behavior) { |
187 instant_complete_behavior_ = behavior; | 186 if (behavior == INSTANT_COMPLETE_NOW) { |
188 if (instant_complete_behavior_ == INSTANT_COMPLETE_NOW) { | |
189 if (!text.empty()) | 187 if (!text.empty()) |
190 FinalizeInstantQuery(view_->GetText(), text, false); | 188 FinalizeInstantQuery(view_->GetText(), text, false); |
191 else | 189 else |
192 view_->SetInstantSuggestion(text, false); | 190 view_->SetInstantSuggestion(text, false); |
193 } else { | 191 } else { |
194 DCHECK((behavior == INSTANT_COMPLETE_DELAYED) || | 192 DCHECK((behavior == INSTANT_COMPLETE_DELAYED) || |
195 (behavior == INSTANT_COMPLETE_NEVER)); | 193 (behavior == INSTANT_COMPLETE_NEVER)); |
196 view_->SetInstantSuggestion(text, behavior == INSTANT_COMPLETE_DELAYED); | 194 view_->SetInstantSuggestion(text, behavior == INSTANT_COMPLETE_DELAYED); |
197 } | 195 } |
198 } | 196 } |
199 | 197 |
200 bool OmniboxEditModel::CommitSuggestedText(bool skip_inline_autocomplete) { | 198 bool OmniboxEditModel::CommitSuggestedText(bool skip_inline_autocomplete) { |
201 if (!controller_->GetInstant()) | 199 if (!controller_->GetInstant()) |
202 return false; | 200 return false; |
203 | 201 |
204 const string16 suggestion = view_->GetInstantSuggestion(); | 202 const string16 suggestion = view_->GetInstantSuggestion(); |
205 if (suggestion.empty()) | 203 if (suggestion.empty()) |
206 return false; | 204 return false; |
207 | 205 |
208 FinalizeInstantQuery(view_->GetText(), suggestion, skip_inline_autocomplete); | 206 FinalizeInstantQuery(view_->GetText(), suggestion, skip_inline_autocomplete); |
209 return true; | 207 return true; |
210 } | 208 } |
211 | 209 |
212 bool OmniboxEditModel::AcceptCurrentInstantPreview() { | 210 bool OmniboxEditModel::AcceptCurrentInstantPreview() { |
213 InstantController* instant = controller_->GetInstant(); | 211 InstantController* instant = controller_->GetInstant(); |
214 return instant && instant->CommitIfCurrent(); | 212 return instant && instant->IsCurrent() && |
| 213 instant->CommitCurrentPreview(INSTANT_COMMIT_PRESSED_ENTER); |
215 } | 214 } |
216 | 215 |
217 void OmniboxEditModel::OnChanged() { | 216 void OmniboxEditModel::OnChanged() { |
218 // Don't call CurrentMatch() when there's no editing, as in this case we'll | 217 // Don't call CurrentMatch() when there's no editing, as in this case we'll |
219 // never actually use it. This avoids running the autocomplete providers (and | 218 // never actually use it. This avoids running the autocomplete providers (and |
220 // any systems they then spin up) during startup. | 219 // any systems they then spin up) during startup. |
221 const AutocompleteMatch& current_match = user_input_in_progress_ ? | 220 const AutocompleteMatch& current_match = user_input_in_progress_ ? |
222 CurrentMatch() : AutocompleteMatch(); | 221 CurrentMatch() : AutocompleteMatch(); |
223 | 222 |
224 AutocompleteActionPredictor::Action recommended_action = | 223 AutocompleteActionPredictor::Action recommended_action = |
225 AutocompleteActionPredictor::ACTION_NONE; | 224 AutocompleteActionPredictor::ACTION_NONE; |
226 AutocompleteActionPredictor* action_predictor = | 225 AutocompleteActionPredictor* action_predictor = |
227 user_input_in_progress_ ? | 226 user_input_in_progress_ ? |
228 AutocompleteActionPredictorFactory::GetForProfile(profile_) : NULL; | 227 AutocompleteActionPredictorFactory::GetForProfile(profile_) : NULL; |
229 if (action_predictor) { | 228 if (action_predictor) { |
230 action_predictor->RegisterTransitionalMatches(user_text_, result()); | 229 action_predictor->RegisterTransitionalMatches(user_text_, result()); |
231 // Confer with the AutocompleteActionPredictor to determine what action, if | 230 // Confer with the AutocompleteActionPredictor to determine what action, if |
232 // any, we should take. Get the recommended action here even if we don't | 231 // any, we should take. Get the recommended action here even if we don't |
233 // need it so we can get stats for anyone who is opted in to UMA, but only | 232 // need it so we can get stats for anyone who is opted in to UMA, but only |
234 // get it if the user has actually typed something to avoid constructing it | 233 // get it if the user has actually typed something to avoid constructing it |
235 // before it's needed. Note: This event is triggered as part of startup when | 234 // before it's needed. Note: This event is triggered as part of startup when |
236 // the initial tab transitions to the start page. | 235 // the initial tab transitions to the start page. |
237 recommended_action = | 236 recommended_action = |
238 action_predictor->RecommendAction(user_text_, current_match); | 237 action_predictor->RecommendAction(user_text_, current_match); |
239 } | 238 } |
240 | 239 |
241 UMA_HISTOGRAM_ENUMERATION("AutocompleteActionPredictor.Action", | 240 UMA_HISTOGRAM_ENUMERATION("AutocompleteActionPredictor.Action", |
242 recommended_action, | 241 recommended_action, |
243 AutocompleteActionPredictor::LAST_PREDICT_ACTION); | 242 AutocompleteActionPredictor::LAST_PREDICT_ACTION); |
| 243 |
244 string16 suggested_text; | 244 string16 suggested_text; |
| 245 InstantCompleteBehavior complete_behavior = INSTANT_COMPLETE_NOW; |
245 | 246 |
246 if (DoInstant(current_match, &suggested_text)) { | 247 if (DoInstant(current_match, &suggested_text, &complete_behavior)) { |
247 SetSuggestedText(suggested_text, instant_complete_behavior_); | 248 SetSuggestedText(suggested_text, complete_behavior); |
248 } else { | 249 } else { |
249 switch (recommended_action) { | 250 switch (recommended_action) { |
250 case AutocompleteActionPredictor::ACTION_PRERENDER: | 251 case AutocompleteActionPredictor::ACTION_PRERENDER: |
251 DoPrerender(current_match); | 252 DoPrerender(current_match); |
252 break; | 253 break; |
253 case AutocompleteActionPredictor::ACTION_PRECONNECT: | 254 case AutocompleteActionPredictor::ACTION_PRECONNECT: |
254 DoPreconnect(current_match); | 255 DoPreconnect(current_match); |
255 break; | 256 break; |
256 case AutocompleteActionPredictor::ACTION_NONE: | 257 case AutocompleteActionPredictor::ACTION_NONE: |
257 break; | 258 break; |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 (has_selected_text && inline_autocomplete_text_.empty()) || | 434 (has_selected_text && inline_autocomplete_text_.empty()) || |
434 (paste_state_ != NONE), keyword_is_selected, | 435 (paste_state_ != NONE), keyword_is_selected, |
435 keyword_is_selected || allow_exact_keyword_match_, | 436 keyword_is_selected || allow_exact_keyword_match_, |
436 AutocompleteInput::ALL_MATCHES); | 437 AutocompleteInput::ALL_MATCHES); |
437 } | 438 } |
438 | 439 |
439 void OmniboxEditModel::StopAutocomplete() { | 440 void OmniboxEditModel::StopAutocomplete() { |
440 if (popup_->IsOpen() && !in_revert_) { | 441 if (popup_->IsOpen() && !in_revert_) { |
441 InstantController* instant = controller_->GetInstant(); | 442 InstantController* instant = controller_->GetInstant(); |
442 if (instant && !instant->commit_on_pointer_release()) | 443 if (instant && !instant->commit_on_pointer_release()) |
443 instant->DestroyPreviewContents(); | 444 instant->Hide(); |
444 } | 445 } |
445 | 446 |
446 autocomplete_controller_->Stop(true); | 447 autocomplete_controller_->Stop(true); |
447 } | 448 } |
448 | 449 |
449 bool OmniboxEditModel::CanPasteAndGo(const string16& text) const { | 450 bool OmniboxEditModel::CanPasteAndGo(const string16& text) const { |
450 if (!view_->GetCommandUpdater()->IsCommandEnabled(IDC_OPEN_CURRENT_URL)) | 451 if (!view_->GetCommandUpdater()->IsCommandEnabled(IDC_OPEN_CURRENT_URL)) |
451 return false; | 452 return false; |
452 | 453 |
453 AutocompleteMatch match; | 454 AutocompleteMatch match; |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 } else { | 606 } else { |
606 controller_->OnAutocompleteAccept(match.destination_url, disposition, | 607 controller_->OnAutocompleteAccept(match.destination_url, disposition, |
607 match.transition, alternate_nav_url); | 608 match.transition, alternate_nav_url); |
608 } | 609 } |
609 | 610 |
610 if (match.starred) | 611 if (match.starred) |
611 bookmark_utils::RecordBookmarkLaunch(bookmark_utils::LAUNCH_OMNIBOX); | 612 bookmark_utils::RecordBookmarkLaunch(bookmark_utils::LAUNCH_OMNIBOX); |
612 | 613 |
613 InstantController* instant = controller_->GetInstant(); | 614 InstantController* instant = controller_->GetInstant(); |
614 if (instant && !popup_->IsOpen()) | 615 if (instant && !popup_->IsOpen()) |
615 instant->DestroyPreviewContents(); | 616 instant->Hide(); |
616 in_revert_ = false; | 617 in_revert_ = false; |
617 } | 618 } |
618 | 619 |
619 bool OmniboxEditModel::AcceptKeyword() { | 620 bool OmniboxEditModel::AcceptKeyword() { |
620 DCHECK(is_keyword_hint_ && !keyword_.empty()); | 621 DCHECK(is_keyword_hint_ && !keyword_.empty()); |
621 | 622 |
622 autocomplete_controller_->Stop(false); | 623 autocomplete_controller_->Stop(false); |
623 is_keyword_hint_ = false; | 624 is_keyword_hint_ = false; |
624 | 625 |
625 if (popup_->IsOpen()) | 626 if (popup_->IsOpen()) |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 InstantController* instant = controller_->GetInstant(); | 676 InstantController* instant = controller_->GetInstant(); |
676 if (instant) | 677 if (instant) |
677 instant->OnAutocompleteGotFocus(); | 678 instant->OnAutocompleteGotFocus(); |
678 | 679 |
679 NotifySearchTabHelper(); | 680 NotifySearchTabHelper(); |
680 } | 681 } |
681 | 682 |
682 void OmniboxEditModel::OnWillKillFocus(gfx::NativeView view_gaining_focus) { | 683 void OmniboxEditModel::OnWillKillFocus(gfx::NativeView view_gaining_focus) { |
683 SetSuggestedText(string16(), INSTANT_COMPLETE_NOW); | 684 SetSuggestedText(string16(), INSTANT_COMPLETE_NOW); |
684 | 685 |
685 InstantController* instant = controller_->GetInstant(); | 686 if (InstantController* instant = controller_->GetInstant()) |
686 if (instant) | |
687 instant->OnAutocompleteLostFocus(view_gaining_focus); | 687 instant->OnAutocompleteLostFocus(view_gaining_focus); |
688 | 688 |
689 NotifySearchTabHelper(); | 689 NotifySearchTabHelper(); |
690 } | 690 } |
691 | 691 |
692 void OmniboxEditModel::OnKillFocus() { | 692 void OmniboxEditModel::OnKillFocus() { |
693 has_focus_ = false; | 693 has_focus_ = false; |
694 control_key_state_ = UP; | 694 control_key_state_ = UP; |
695 paste_state_ = NONE; | 695 paste_state_ = NONE; |
696 } | 696 } |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1079 GetKeywordForText(keyword).empty(); | 1079 GetKeywordForText(keyword).empty(); |
1080 } | 1080 } |
1081 | 1081 |
1082 void OmniboxEditModel::NotifySearchTabHelper() { | 1082 void OmniboxEditModel::NotifySearchTabHelper() { |
1083 if (controller_->GetTabContents()) { | 1083 if (controller_->GetTabContents()) { |
1084 controller_->GetTabContents()->search_tab_helper()-> | 1084 controller_->GetTabContents()->search_tab_helper()-> |
1085 OmniboxEditModelChanged(this); | 1085 OmniboxEditModelChanged(this); |
1086 } | 1086 } |
1087 } | 1087 } |
1088 | 1088 |
1089 bool OmniboxEditModel::DoInstant(const AutocompleteMatch& match, | 1089 bool OmniboxEditModel::DoInstant( |
1090 string16* suggested_text) { | 1090 const AutocompleteMatch& match, |
| 1091 string16* suggested_text, |
| 1092 InstantCompleteBehavior* complete_behavior) { |
1091 DCHECK(suggested_text); | 1093 DCHECK(suggested_text); |
| 1094 DCHECK(complete_behavior); |
1092 | 1095 |
1093 if (in_revert_) | 1096 if (in_revert_) |
1094 return false; | 1097 return false; |
1095 | 1098 |
1096 InstantController* instant = controller_->GetInstant(); | 1099 InstantController* instant = controller_->GetInstant(); |
1097 | 1100 |
1098 if (!instant) | 1101 if (!instant) |
1099 return false; | 1102 return false; |
1100 | 1103 |
1101 if (user_input_in_progress_ && popup_->IsOpen()) { | 1104 if (user_input_in_progress_ && popup_->IsOpen()) { |
1102 return instant->Update(match, view_->GetText(), UseVerbatimInstant(), | 1105 string16 text = view_->GetText(); |
1103 suggested_text); | 1106 AutocompleteInput::RemoveForcedQueryStringIfNecessary( |
| 1107 autocomplete_controller_->input().type(), &text); |
| 1108 |
| 1109 // If there's any inline autocompletion, split it out from |text|. |
| 1110 if (!inline_autocomplete_text_.empty()) { |
| 1111 DCHECK_GE(text.size(), inline_autocomplete_text_.size()); |
| 1112 text.resize(text.size() - inline_autocomplete_text_.size()); |
| 1113 *suggested_text = inline_autocomplete_text_; |
| 1114 } |
| 1115 |
| 1116 return instant->Update(match, text, UseVerbatimInstant(), suggested_text, |
| 1117 complete_behavior); |
1104 } | 1118 } |
1105 | 1119 |
1106 // It's possible DoInstant() was called due to an OnChanged() event from the | 1120 // It's possible DoInstant() was called due to an OnChanged() event from the |
1107 // omnibox view if the user clicked the renderer while IME composition was | 1121 // omnibox view if the user clicked the renderer while IME composition was |
1108 // active. In that case we still want to commit on mouse up, so don't call | 1122 // active. In that case we still want to commit on mouse up, so don't call |
1109 // Hide(). | 1123 // Hide(). |
1110 if (!instant->commit_on_pointer_release()) | 1124 if (!instant->commit_on_pointer_release()) |
1111 instant->Hide(); | 1125 instant->Hide(); |
1112 return false; | 1126 return false; |
1113 } | 1127 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1173 } | 1187 } |
1174 | 1188 |
1175 void OmniboxEditModel::ClassifyStringForPasteAndGo( | 1189 void OmniboxEditModel::ClassifyStringForPasteAndGo( |
1176 const string16& text, | 1190 const string16& text, |
1177 AutocompleteMatch* match, | 1191 AutocompleteMatch* match, |
1178 GURL* alternate_nav_url) const { | 1192 GURL* alternate_nav_url) const { |
1179 DCHECK(match); | 1193 DCHECK(match); |
1180 AutocompleteClassifierFactory::GetForProfile(profile_)->Classify(text, | 1194 AutocompleteClassifierFactory::GetForProfile(profile_)->Classify(text, |
1181 string16(), false, false, match, alternate_nav_url); | 1195 string16(), false, false, match, alternate_nav_url); |
1182 } | 1196 } |
OLD | NEW |