Commit 9adc9dce authored by suzhe@google.com's avatar suzhe@google.com

Allow space to accept keyword even when inline autocomplete is available.

This CL assumes keyword query is always synchronous.

BUG=70527
TEST=See bug report.

Review URL: http://codereview.chromium.org/6281011

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@72457 0039d316-1c4b-4281-b951-d872f2087c98
parent cde035b0
...@@ -645,20 +645,12 @@ bool AutocompleteEditModel::OnAfterPossibleChange( ...@@ -645,20 +645,12 @@ bool AutocompleteEditModel::OnAfterPossibleChange(
return false; return false;
} }
const std::wstring old_user_text = user_text_;
// If the user text has not changed, we do not want to change the model's // 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 // state associated with the text. Otherwise, we can get surprising behavior
// where the autocompleted text unexpectedly reappears, e.g. crbug.com/55983 // where the autocompleted text unexpectedly reappears, e.g. crbug.com/55983
if (user_text_changed) { if (user_text_changed) {
const std::wstring new_user_text = UserTextFromDisplayText(new_text); InternalSetUserText(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; has_temporary_text_ = false;
// Track when the user has deleted text so we won't allow inline // Track when the user has deleted text so we won't allow inline
...@@ -667,6 +659,14 @@ bool AutocompleteEditModel::OnAfterPossibleChange( ...@@ -667,6 +659,14 @@ bool AutocompleteEditModel::OnAfterPossibleChange(
} }
view_->UpdatePopup(); view_->UpdatePopup();
// Change to keyword mode if the user has typed a keyword name and is now
// pressing space after the name. Accepting the keyword will update our
// state, so in that case there's no need to also return true here.
if (text_differs && allow_keyword_ui_change && !just_deleted_text &&
MaybeAcceptKeywordBySpace(old_user_text, user_text_))
return false;
return true; return true;
} }
...@@ -782,13 +782,15 @@ bool AutocompleteEditModel::GetURLForText(const std::wstring& text, ...@@ -782,13 +782,15 @@ bool AutocompleteEditModel::GetURLForText(const std::wstring& text,
} }
bool AutocompleteEditModel::MaybeAcceptKeywordBySpace( bool AutocompleteEditModel::MaybeAcceptKeywordBySpace(
const std::wstring& old_user_text,
const std::wstring& new_user_text) { const std::wstring& new_user_text) {
return (paste_state_ == NONE) && is_keyword_hint_ && !keyword_.empty() && return (paste_state_ == NONE) && is_keyword_hint_ && !keyword_.empty() &&
inline_autocomplete_text_.empty() && !user_text_.empty() && inline_autocomplete_text_.empty() && new_user_text.length() >= 2 &&
(new_user_text.length() == user_text_.length() + 1) && IsSpaceCharForAcceptingKeyword(*new_user_text.rbegin()) &&
!new_user_text.compare(0, user_text_.length(), user_text_) && !IsWhitespace(*(new_user_text.rbegin() + 1)) &&
IsSpaceCharForAcceptingKeyword(new_user_text[user_text_.length()]) && (old_user_text.length() + 1 >= new_user_text.length()) &&
!IsWhitespace(user_text_[user_text_.length() - 1]) && !new_user_text.compare(0, new_user_text.length() - 1, old_user_text,
0, new_user_text.length() - 1) &&
AcceptKeyword(); AcceptKeyword();
} }
......
...@@ -379,8 +379,10 @@ class AutocompleteEditModel : public NotificationObserver { ...@@ -379,8 +379,10 @@ class AutocompleteEditModel : public NotificationObserver {
bool GetURLForText(const std::wstring& text, GURL* url) const; bool GetURLForText(const std::wstring& text, GURL* url) const;
// Accepts current keyword if the user only typed a space at the end of // Accepts current keyword if the user only typed a space at the end of
// |new_user_text|. Returns true if the current keyword is accepted. // |new_user_text| comparing to the |old_user_text|.
bool MaybeAcceptKeywordBySpace(const std::wstring& new_user_text); // Returns true if the current keyword is accepted.
bool MaybeAcceptKeywordBySpace(const std::wstring& old_user_text,
const std::wstring& new_user_text);
// Checks if a given character is a valid space character for accepting // Checks if a given character is a valid space character for accepting
// keyword. // keyword.
......
...@@ -254,7 +254,7 @@ class AutocompleteEditViewTest : public InProcessBrowserTest, ...@@ -254,7 +254,7 @@ class AutocompleteEditViewTest : public InProcessBrowserTest,
model->SetDefaultSearchProvider(template_url); model->SetDefaultSearchProvider(template_url);
} }
void SetupHistory() { void AddHistoryEntry(const TestHistoryEntry& entry, const Time& time) {
Profile* profile = browser()->profile(); Profile* profile = browser()->profile();
HistoryService* history_service = HistoryService* history_service =
profile->GetHistoryService(Profile::EXPLICIT_ACCESS); profile->GetHistoryService(Profile::EXPLICIT_ACCESS);
...@@ -277,22 +277,26 @@ class AutocompleteEditViewTest : public InProcessBrowserTest, ...@@ -277,22 +277,26 @@ class AutocompleteEditViewTest : public InProcessBrowserTest,
ui_test_utils::RunMessageLoop(); ui_test_utils::RunMessageLoop();
} }
GURL url(entry.url);
// Add everything in order of time. We don't want to have a time that
// is "right now" or it will nondeterministically appear in the results.
history_service->AddPageWithDetails(url, UTF8ToUTF16(entry.title),
entry.visit_count,
entry.typed_count, time, false,
history::SOURCE_BROWSED);
history_service->SetPageContents(url, UTF8ToUTF16(entry.body));
if (entry.starred)
bookmark_model->SetURLStarred(url, string16(), true);
}
void SetupHistory() {
// Add enough history pages containing |kSearchText| to trigger // Add enough history pages containing |kSearchText| to trigger
// open history page url in autocomplete result. // open history page url in autocomplete result.
for (size_t i = 0; i < arraysize(kHistoryEntries); i++) { for (size_t i = 0; i < arraysize(kHistoryEntries); i++) {
const TestHistoryEntry& cur = kHistoryEntries[i];
GURL url(cur.url);
// Add everything in order of time. We don't want to have a time that // Add everything in order of time. We don't want to have a time that
// is "right now" or it will nondeterministically appear in the results. // is "right now" or it will nondeterministically appear in the results.
Time t = Time::Now() - TimeDelta::FromHours(i + 1); Time t = Time::Now() - TimeDelta::FromHours(i + 1);
history_service->AddPageWithDetails(url, UTF8ToUTF16(cur.title), ASSERT_NO_FATAL_FAILURE(AddHistoryEntry(kHistoryEntries[i], t));
cur.visit_count,
cur.typed_count, t, false,
history::SOURCE_BROWSED);
history_service->SetPageContents(url, UTF8ToUTF16(cur.body));
if (cur.starred) {
bookmark_model->SetURLStarred(url, string16(), true);
}
} }
} }
...@@ -738,7 +742,8 @@ class AutocompleteEditViewTest : public InProcessBrowserTest, ...@@ -738,7 +742,8 @@ class AutocompleteEditViewTest : public InProcessBrowserTest,
ASSERT_TRUE(edit_view->model()->keyword().empty()); ASSERT_TRUE(edit_view->model()->keyword().empty());
ASSERT_EQ(text + L" bar", edit_view->GetText()); ASSERT_EQ(text + L" bar", edit_view->GetText());
// Keyword shouldn't be accepted by pressing space with a selected range. // Keyword could be accepted by pressing space with a selected range at the
// end of text.
edit_view->OnBeforePossibleChange(); edit_view->OnBeforePossibleChange();
edit_view->OnInlineAutocompleteTextMaybeChanged( edit_view->OnInlineAutocompleteTextMaybeChanged(
text + L" ", text.length()); text + L" ", text.length());
...@@ -751,12 +756,36 @@ class AutocompleteEditViewTest : public InProcessBrowserTest, ...@@ -751,12 +756,36 @@ class AutocompleteEditViewTest : public InProcessBrowserTest,
edit_view->GetSelectionBounds(&start, &end); edit_view->GetSelectionBounds(&start, &end);
ASSERT_NE(start, end); ASSERT_NE(start, end);
ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, false, false, false)); ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, false, false, false));
ASSERT_TRUE(edit_view->model()->is_keyword_hint()); ASSERT_FALSE(edit_view->model()->is_keyword_hint());
ASSERT_EQ(text, edit_view->model()->keyword()); ASSERT_EQ(text, edit_view->model()->keyword());
ASSERT_EQ(text + L" ", edit_view->GetText()); ASSERT_EQ(std::wstring(), edit_view->GetText());
edit_view->GetSelectionBounds(&start, &end); edit_view->SetUserText(std::wstring());
ASSERT_EQ(start, end);
// Space should accept keyword even when inline autocomplete is available.
const TestHistoryEntry kHistoryFoobar = {
"http://www.foobar.com", "Page foobar", kSearchText, 10000, 10000, true
};
// Add a history entry to trigger inline autocomplete when typing "foo".
ASSERT_NO_FATAL_FAILURE(
AddHistoryEntry(kHistoryFoobar, Time::Now() - TimeDelta::FromHours(1)));
// Type "foo" to trigger inline autocomplete.
ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchKeywordKeys));
ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone());
ASSERT_TRUE(edit_view->model()->popup_model()->IsOpen());
ASSERT_NE(text, edit_view->GetText());
// Keyword hint shouldn't be visible.
ASSERT_FALSE(edit_view->model()->is_keyword_hint());
ASSERT_TRUE(edit_view->model()->keyword().empty());
// Trigger keyword mode by space.
ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_SPACE, false, false, false));
ASSERT_FALSE(edit_view->model()->is_keyword_hint());
ASSERT_EQ(text, edit_view->model()->keyword());
ASSERT_TRUE(edit_view->GetText().empty());
} }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment