Index: chrome/browser/autocomplete/autocomplete_edit.cc |
diff --git a/chrome/browser/autocomplete/autocomplete_edit.cc b/chrome/browser/autocomplete/autocomplete_edit.cc |
index c4d782a07b4c081d1d2baa35e4209f24db282a64..1ad993eeb638778287a9157989000b414948c009 100644 |
--- a/chrome/browser/autocomplete/autocomplete_edit.cc |
+++ b/chrome/browser/autocomplete/autocomplete_edit.cc |
@@ -45,13 +45,11 @@ AutocompleteEditController::~AutocompleteEditController() { |
AutocompleteEditModel::State::State(bool user_input_in_progress, |
const std::wstring& user_text, |
const std::wstring& keyword, |
- bool is_keyword_hint, |
- KeywordUIState keyword_ui_state) |
+ bool is_keyword_hint) |
: user_input_in_progress(user_input_in_progress), |
user_text(user_text), |
keyword(keyword), |
- is_keyword_hint(is_keyword_hint), |
- keyword_ui_state(keyword_ui_state) { |
+ is_keyword_hint(is_keyword_hint) { |
} |
AutocompleteEditModel::State::~State() { |
@@ -71,11 +69,9 @@ AutocompleteEditModel::AutocompleteEditModel( |
user_input_in_progress_(false), |
just_deleted_text_(false), |
has_temporary_text_(false), |
- original_keyword_ui_state_(NORMAL), |
paste_state_(NONE), |
control_key_state_(UP), |
is_keyword_hint_(false), |
- keyword_ui_state_(NORMAL), |
paste_and_go_transition_(PageTransition::TYPED), |
profile_(profile) { |
} |
@@ -114,8 +110,7 @@ const AutocompleteEditModel::State |
} |
} |
- return State(user_input_in_progress_, user_text_, keyword_, is_keyword_hint_, |
- keyword_ui_state_); |
+ return State(user_input_in_progress_, user_text_, keyword_, is_keyword_hint_); |
} |
void AutocompleteEditModel::RestoreState(const State& state) { |
@@ -125,7 +120,6 @@ void AutocompleteEditModel::RestoreState(const State& state) { |
// DisplayTextFromUserText(), as its result depends upon this state. |
keyword_ = state.keyword; |
is_keyword_hint_ = state.is_keyword_hint; |
- keyword_ui_state_ = state.keyword_ui_state; |
view_->SetUserText(state.user_text, |
DisplayTextFromUserText(state.user_text), false); |
} |
@@ -296,7 +290,6 @@ void AutocompleteEditModel::Revert() { |
InternalSetUserText(std::wstring()); |
keyword_.clear(); |
is_keyword_hint_ = false; |
- keyword_ui_state_ = NORMAL; |
has_temporary_text_ = false; |
view_->SetWindowTextAndCaretPos(permanent_text_, |
has_focus_ ? permanent_text_.length() : 0); |
@@ -305,11 +298,11 @@ void AutocompleteEditModel::Revert() { |
void AutocompleteEditModel::StartAutocomplete( |
bool has_selected_text, |
bool prevent_inline_autocomplete) const { |
+ bool keyword_is_selected = KeywordIsSelected(); |
popup_->StartAutocomplete(user_text_, GetDesiredTLD(), |
prevent_inline_autocomplete || just_deleted_text_ || |
(has_selected_text && inline_autocomplete_text_.empty()) || |
- (paste_state_ != NONE), keyword_ui_state_ == KEYWORD, |
- keyword_ui_state_ != NO_KEYWORD); |
+ (paste_state_ != NONE), keyword_is_selected, keyword_is_selected); |
} |
bool AutocompleteEditModel::CanPasteAndGo(const std::wstring& text) const { |
@@ -438,17 +431,19 @@ void AutocompleteEditModel::OpenURL(const GURL& url, |
alternate_nav_url); |
} |
-void AutocompleteEditModel::AcceptKeyword() { |
+bool AutocompleteEditModel::AcceptKeyword() { |
+ DCHECK(is_keyword_hint_ && !keyword_.empty()); |
+ |
view_->OnBeforePossibleChange(); |
view_->SetWindowTextAndCaretPos(std::wstring(), 0); |
is_keyword_hint_ = false; |
- keyword_ui_state_ = KEYWORD; |
view_->OnAfterPossibleChange(); |
just_deleted_text_ = false; // OnAfterPossibleChange() erroneously sets this |
// since the edit contents have disappeared. It |
// doesn't really matter, but we clear it to be |
// consistent. |
UserMetrics::RecordAction(UserMetricsAction("AcceptedKeywordHint"), profile_); |
+ return true; |
} |
void AutocompleteEditModel::ClearKeyword(const std::wstring& visible_text) { |
@@ -456,7 +451,7 @@ void AutocompleteEditModel::ClearKeyword(const std::wstring& visible_text) { |
const std::wstring window_text(keyword_ + visible_text); |
view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length()); |
keyword_.clear(); |
- keyword_ui_state_ = NORMAL; |
+ is_keyword_hint_ = false; |
view_->OnAfterPossibleChange(); |
just_deleted_text_ = true; // OnAfterPossibleChange() fails to clear this |
// since the edit contents have actually grown |
@@ -502,7 +497,6 @@ bool AutocompleteEditModel::OnEscapeKeyPressed() { |
// NOTE: This purposefully does not reset paste_state_. |
just_deleted_text_ = false; |
has_temporary_text_ = false; |
- keyword_ui_state_ = original_keyword_ui_state_; |
popup_->ResetToDefaultMatch(); |
view_->OnRevertTemporaryText(); |
return true; |
@@ -576,21 +570,15 @@ void AutocompleteEditModel::OnPopupDataChanged( |
GURL* destination_for_temporary_text_change, |
const std::wstring& keyword, |
bool is_keyword_hint) { |
- KeywordUIState old_keyword_ui_state = keyword_ui_state_; |
- |
// Update keyword/hint-related local state. |
bool keyword_state_changed = (keyword_ != keyword) || |
((is_keyword_hint_ != is_keyword_hint) && !keyword.empty()); |
if (keyword_state_changed) { |
keyword_ = keyword; |
is_keyword_hint_ = is_keyword_hint; |
- } |
- // Update |keyword_ui_state_| only when necessary. It may be changed even if |
- // |keyword_state_changed| is false. |
- if (keyword_ui_state_ != NO_KEYWORD) { |
- keyword_ui_state_ = (is_keyword_hint_ || keyword_.empty()) ? |
- NORMAL : KEYWORD; |
+ // |is_keyword_hint_| should always be false if |keyword_| is empty. |
+ DCHECK(!keyword_.empty() || !is_keyword_hint_); |
} |
// Handle changes to temporary text. |
@@ -600,7 +588,6 @@ void AutocompleteEditModel::OnPopupDataChanged( |
// Save the original selection and URL so it can be reverted later. |
has_temporary_text_ = true; |
original_url_ = *destination_for_temporary_text_change; |
- original_keyword_ui_state_ = old_keyword_ui_state; |
inline_autocomplete_text_.clear(); |
} |
if (control_key_state_ == DOWN_WITHOUT_CHANGE) { |
@@ -643,8 +630,8 @@ bool AutocompleteEditModel::OnAfterPossibleChange( |
// Update the paste state as appropriate: if we're just finishing a paste |
// that replaced all the text, preserve that information; otherwise, if we've |
// made some other edit, clear paste tracking. |
- if (paste_state_ == REPLACING_ALL) |
- paste_state_ = REPLACED_ALL; |
+ if (paste_state_ == PASTING) |
+ paste_state_ = PASTED; |
else if (text_differs) |
paste_state_ = NONE; |
@@ -664,13 +651,20 @@ bool AutocompleteEditModel::OnAfterPossibleChange( |
return false; |
} |
- const bool had_keyword = KeywordIsSelected(); |
- |
// If the user text has not changed, we do not want to change the model's |
// state associated with the text. Otherwise, we can get surprising behavior |
// where the autocompleted text unexpectedly reappears, e.g. crbug.com/55983 |
if (user_text_changed) { |
- InternalSetUserText(UserTextFromDisplayText(new_text)); |
+ const std::wstring new_user_text = UserTextFromDisplayText(new_text); |
+ |
+ // Try to accept the current keyword if the user only typed a space at the |
+ // end of content. Model's state and popup will be updated when the keyword |
+ // is accepted. So we just need to return false here. |
+ if (allow_keyword_ui_change && !selection_differs && |
+ MaybeAcceptKeywordBySpace(new_user_text)) |
+ return false; |
+ |
+ InternalSetUserText(new_user_text); |
has_temporary_text_ = false; |
// Track when the user has deleted text so we won't allow inline |
@@ -678,17 +672,6 @@ bool AutocompleteEditModel::OnAfterPossibleChange( |
just_deleted_text_ = just_deleted_text; |
} |
- // Disable the fancy keyword UI if the user didn't already have a visible |
- // keyword and the view doesn't want us to change the keyword UI state. |
- // This prevents us from showing the fancy UI and interrupting the user's |
- // editing if, for example, the user happens to have a keyword for 'a', |
- // types 'ab' then puts a space between the 'a' and the 'b'. |
- // If |keyword_ui_state_| is set to NORMAL here, then it will be updated |
- // to a proper value in OnPopupDataChanged() method according to the new |
- // match result. |
- if (!had_keyword) |
- keyword_ui_state_ = allow_keyword_ui_change ? NORMAL : NO_KEYWORD; |
- |
view_->UpdatePopup(); |
return true; |
} |
@@ -758,7 +741,7 @@ void AutocompleteEditModel::InternalSetUserText(const std::wstring& text) { |
} |
bool AutocompleteEditModel::KeywordIsSelected() const { |
- return keyword_ui_state_ == KEYWORD; |
+ return !is_keyword_hint_ && !keyword_.empty(); |
} |
std::wstring AutocompleteEditModel::DisplayTextFromUserText( |
@@ -795,3 +778,25 @@ bool AutocompleteEditModel::GetURLForText(const std::wstring& text, |
*url = parsed_url; |
return true; |
} |
+ |
+bool AutocompleteEditModel::MaybeAcceptKeywordBySpace( |
+ const std::wstring& new_user_text) { |
+ return (paste_state_ == NONE) && is_keyword_hint_ && !keyword_.empty() && |
+ inline_autocomplete_text_.empty() && !user_text_.empty() && |
+ (new_user_text.length() == user_text_.length() + 1) && |
+ !new_user_text.compare(0, user_text_.length(), user_text_) && |
+ IsSpaceCharForAcceptingKeyword(new_user_text[user_text_.length()]) && |
+ !IsWhitespace(user_text_[user_text_.length() - 1]) && |
+ AcceptKeyword(); |
+} |
+ |
+// static |
+bool AutocompleteEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { |
+ switch (c) { |
+ case 0x0020: // Space |
+ case 0x3000: // Ideographic Space |
+ return true; |
+ default: |
+ return false; |
+ } |
+} |