summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/autocomplete_history_manager.cc4
-rw-r--r--chrome/browser/autofill/autofill_manager_unittest.cc75
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc46
-rw-r--r--chrome/browser/renderer_host/render_view_host.h9
-rw-r--r--chrome/common/render_messages_internal.h7
-rw-r--r--chrome/renderer/render_view.cc74
-rw-r--r--chrome/renderer/render_view.h7
-rw-r--r--chrome/renderer/render_view_unittest.cc12
-rw-r--r--webkit/glue/webpasswordautocompletelistener_impl.cc19
-rw-r--r--webkit/glue/webpasswordautocompletelistener_impl.h3
10 files changed, 180 insertions, 76 deletions
diff --git a/chrome/browser/autocomplete_history_manager.cc b/chrome/browser/autocomplete_history_manager.cc
index 12c661e..f30ec2b 100644
--- a/chrome/browser/autocomplete_history_manager.cc
+++ b/chrome/browser/autocomplete_history_manager.cc
@@ -179,9 +179,9 @@ void AutocompleteHistoryManager::SendSuggestions(const WDTypedResult* result) {
const WDResult<std::vector<string16> >* autofill_result =
static_cast<const WDResult<std::vector<string16> >*>(result);
host->AutocompleteSuggestionsReturned(
- query_id_, autofill_result->GetValue(), -1);
+ query_id_, autofill_result->GetValue());
} else {
host->AutocompleteSuggestionsReturned(
- query_id_, std::vector<string16>(), -1);
+ query_id_, std::vector<string16>());
}
}
diff --git a/chrome/browser/autofill/autofill_manager_unittest.cc b/chrome/browser/autofill/autofill_manager_unittest.cc
index e989269..1549079 100644
--- a/chrome/browser/autofill/autofill_manager_unittest.cc
+++ b/chrome/browser/autofill/autofill_manager_unittest.cc
@@ -285,6 +285,10 @@ TEST_F(AutoFillManagerTest, GetProfileSuggestionsEmptyValue) {
"First Name", "firstname", "", "text", &field);
EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, false, field));
+ // No suggestions provided, so send an empty vector as the results.
+ // This triggers the combined message send.
+ rvh()->AutocompleteSuggestionsReturned(kPageID, std::vector<string16>());
+
// Test that we sent the right message to the renderer.
int page_id = 0;
std::vector<string16> values;
@@ -317,6 +321,10 @@ TEST_F(AutoFillManagerTest, GetProfileSuggestionsMatchCharacter) {
"First Name", "firstname", "E", "text", &field);
EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, false, field));
+ // No suggestions provided, so send an empty vector as the results.
+ // This triggers the combined message send.
+ rvh()->AutocompleteSuggestionsReturned(kPageID, std::vector<string16>());
+
// Test that we sent the right message to the renderer.
int page_id = 0;
std::vector<string16> values;
@@ -347,6 +355,10 @@ TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsEmptyValue) {
"Card Number", "cardnumber", "", "text", &field);
EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, false, field));
+ // No suggestions provided, so send an empty vector as the results.
+ // This triggers the combined message send.
+ rvh()->AutocompleteSuggestionsReturned(kPageID, std::vector<string16>());
+
// Test that we sent the right message to the renderer.
int page_id = 0;
std::vector<string16> values;
@@ -387,6 +399,10 @@ TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsMatchCharacter) {
"Card Number", "cardnumber", "1", "text", &field);
EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, false, field));
+ // No suggestions provided, so send an empty vector as the results.
+ // This triggers the combined message send.
+ rvh()->AutocompleteSuggestionsReturned(kPageID, std::vector<string16>());
+
// Test that we sent the right message to the renderer.
int page_id = 0;
std::vector<string16> values;
@@ -421,6 +437,10 @@ TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsNonCCNumber) {
"Name on Card", "nameoncard", "", "text", &field);
EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, false, field));
+ // No suggestions provided, so send an empty vector as the results.
+ // This triggers the combined message send.
+ rvh()->AutocompleteSuggestionsReturned(kPageID, std::vector<string16>());
+
// Test that we sent the right message to the renderer.
int page_id = 0;
std::vector<string16> values;
@@ -470,6 +490,10 @@ TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsSemicolon) {
"Name on Card", "nameoncard", "", "text", &field);
EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, false, field));
+ // No suggestions provided, so send an empty vector as the results.
+ // This triggers the combined message send.
+ rvh()->AutocompleteSuggestionsReturned(kPageID, std::vector<string16>());
+
// Test that we sent the right message to the renderer.
int page_id = 0;
std::vector<string16> values;
@@ -496,6 +520,49 @@ TEST_F(AutoFillManagerTest, GetCreditCardSuggestionsSemicolon) {
EXPECT_EQ(ASCIIToUTF16("Home; 8765; 8765"), labels[7]);
}
+TEST_F(AutoFillManagerTest, GetCombinedAutoFillAndAutocompleteSuggestions) {
+ FormData form;
+ CreateTestFormData(&form);
+
+ // Set up our FormStructures.
+ std::vector<FormData> forms;
+ forms.push_back(form);
+ autofill_manager_->FormsSeen(forms);
+
+ // The page ID sent to the AutoFillManager from the RenderView, used to send
+ // an IPC message back to the renderer.
+ const int kPageID = 1;
+
+ webkit_glue::FormField field;
+ autofill_unittest::CreateTestFormField(
+ "First Name", "firstname", "", "text", &field);
+ EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, false, field));
+
+ // Add some Autocomplete suggestions.
+ // This triggers the combined message send.
+ std::vector<string16> suggestions;
+ suggestions.push_back(ASCIIToUTF16("Jay"));
+ suggestions.push_back(ASCIIToUTF16("Jason"));
+ rvh()->AutocompleteSuggestionsReturned(kPageID, suggestions);
+
+ // Test that we sent the right message to the renderer.
+ int page_id = 0;
+ std::vector<string16> values;
+ std::vector<string16> labels;
+ EXPECT_TRUE(GetAutoFillSuggestionsMessage(&page_id, &values, &labels));
+ EXPECT_EQ(kPageID, page_id);
+ ASSERT_EQ(4U, values.size());
+ EXPECT_EQ(ASCIIToUTF16("Elvis"), values[0]);
+ EXPECT_EQ(ASCIIToUTF16("Charles"), values[1]);
+ EXPECT_EQ(ASCIIToUTF16("Jay"), values[2]);
+ EXPECT_EQ(ASCIIToUTF16("Jason"), values[3]);
+ ASSERT_EQ(4U, labels.size());
+ EXPECT_EQ(ASCIIToUTF16("Home"), labels[0]);
+ EXPECT_EQ(ASCIIToUTF16("Work"), labels[1]);
+ EXPECT_EQ(string16(), labels[2]);
+ EXPECT_EQ(string16(), labels[3]);
+}
+
TEST_F(AutoFillManagerTest, GetFieldSuggestionsFormIsAutoFilled) {
FormData form;
CreateTestFormData(&form);
@@ -514,6 +581,10 @@ TEST_F(AutoFillManagerTest, GetFieldSuggestionsFormIsAutoFilled) {
"First Name", "firstname", "", "text", &field);
EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, true, field));
+ // No suggestions provided, so send an empty vector as the results.
+ // This triggers the combined message send.
+ rvh()->AutocompleteSuggestionsReturned(kPageID, std::vector<string16>());
+
// Test that we sent the right message to the renderer.
int page_id = 0;
std::vector<string16> values;
@@ -552,6 +623,10 @@ TEST_F(AutoFillManagerTest, GetFieldSuggestionsWithDuplicateValues) {
"First Name", "firstname", "", "text", &field);
EXPECT_TRUE(autofill_manager_->GetAutoFillSuggestions(kPageID, true, field));
+ // No suggestions provided, so send an empty vector as the results.
+ // This triggers the combined message send.
+ rvh()->AutocompleteSuggestionsReturned(kPageID, std::vector<string16>());
+
// Test that we sent the right message to the renderer.
int page_id = 0;
std::vector<string16> values;
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index ba6cfac..28b44a3 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -1591,12 +1591,18 @@ void RenderViewHost::OnQueryFormFieldAutoFill(
int query_id, bool form_autofilled, const webkit_glue::FormField& field) {
RenderViewHostDelegate::AutoFill* autofill_delegate =
delegate_->GetAutoFillDelegate();
- // If the AutoFill delegate has results to return, we don't need any results
- // from the Autocomplete delegate.
+ // We first save the AutoFill delegate's suggestions. Then we fetch the
+ // Autocomplete delegate's suggestions and send the combined results back to
+ // the render view.
if (autofill_delegate &&
- autofill_delegate->GetAutoFillSuggestions(
- query_id, form_autofilled, field)) {
- return;
+ autofill_delegate->GetAutoFillSuggestions(query_id,
+ form_autofilled,
+ field)) {
+ } else {
+ // No suggestions provided, so supply an empty vector as the results.
+ AutoFillSuggestionsReturned(query_id,
+ std::vector<string16>(),
+ std::vector<string16>());
}
RenderViewHostDelegate::Autocomplete* autocomplete_delegate =
@@ -1604,11 +1610,10 @@ void RenderViewHost::OnQueryFormFieldAutoFill(
if (autocomplete_delegate &&
autocomplete_delegate->GetAutocompleteSuggestions(
query_id, field.name(), field.value())) {
- return;
+ } else {
+ // No suggestions provided, so send an empty vector as the results.
+ AutocompleteSuggestionsReturned(query_id, std::vector<string16>());
}
-
- // No suggestions provided, so send an empty vector as the results.
- AutocompleteSuggestionsReturned(query_id, std::vector<string16>(), -1);
}
void RenderViewHost::OnRemoveAutocompleteEntry(const string16& field_name,
@@ -1644,16 +1649,25 @@ void RenderViewHost::AutoFillSuggestionsReturned(
int query_id,
const std::vector<string16>& names,
const std::vector<string16>& labels) {
- Send(new ViewMsg_AutoFillSuggestionsReturned(
- routing_id(), query_id, names, labels));
+ autofill_query_id_ = query_id;
+ autofill_values_.clear();
+ autofill_values_.insert(autofill_values_.begin(), names.begin(), names.end());
+ autofill_labels_.clear();
+ autofill_labels_.insert(
+ autofill_labels_.begin(), labels.begin(), labels.end());
}
void RenderViewHost::AutocompleteSuggestionsReturned(
- int query_id, const std::vector<string16>& suggestions,
- int default_suggestion_index) {
- Send(new ViewMsg_AutocompleteSuggestionsReturned(
- routing_id(), query_id, suggestions, -1));
- // Default index -1 means no default suggestion.
+ int query_id, const std::vector<string16>& suggestions) {
+ DCHECK_EQ(autofill_query_id_, query_id);
+
+ // Combine AutoFill and Autocomplete values into values and labels.
+ for (size_t i = 0; i < suggestions.size(); ++i) {
+ autofill_values_.push_back(suggestions[i]);
+ autofill_labels_.push_back(string16());
+ }
+ Send(new ViewMsg_AutoFillSuggestionsReturned(
+ routing_id(), query_id, autofill_values_, autofill_labels_));
}
void RenderViewHost::AutoFillFormDataFilled(int query_id,
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index 90f600d..25d3c15 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -393,8 +393,7 @@ class RenderViewHost : public RenderWidgetHost {
// ready.
void AutocompleteSuggestionsReturned(
int query_id,
- const std::vector<string16>& suggestions,
- int default_suggestion_index);
+ const std::vector<string16>& suggestions);
// Called by the AutoFillManager when the FormData has been filled out.
void AutoFillFormDataFilled(int query_id, const webkit_glue::FormData& form);
@@ -718,6 +717,12 @@ class RenderViewHost : public RenderWidgetHost {
// what process type we use.
bool is_extension_process_;
+ // AutoFill and Autocomplete suggestions. We accumulate these separately and
+ // send them back to the renderer together.
+ int autofill_query_id_;
+ std::vector<string16> autofill_values_;
+ std::vector<string16> autofill_labels_;
+
DISALLOW_COPY_AND_ASSIGN(RenderViewHost);
};
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 421e4fb..042b7c6 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -637,13 +637,6 @@ IPC_BEGIN_MESSAGES(View)
std::vector<string16> /* names */,
std::vector<string16> /* labels */)
- // Reply to the ViewHostMsg_QueryFormFieldAutofill message with the
- // Autocomplete suggestions.
- IPC_MESSAGE_ROUTED3(ViewMsg_AutocompleteSuggestionsReturned,
- int /* id of the request message */,
- std::vector<string16> /* suggestions */,
- int /* index of default suggestion */)
-
// Reply to the ViewHostMsg_FillAutoFillFormData message with the
// AutoFill form data.
IPC_MESSAGE_ROUTED2(ViewMsg_AutoFillFormDataFilled,
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index f05e975..004c31c 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -433,7 +433,8 @@ RenderView::RenderView(RenderThreadBase* render_thread,
browser_window_id_(-1),
autofill_query_id_(0),
autofill_action_(AUTOFILL_NONE),
- suggestions_count_(0),
+ suggestions_clear_index_(-1),
+ suggestions_options_index_(-1),
ALLOW_THIS_IN_INITIALIZER_LIST(pepper_delegate_(this)),
ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
ALLOW_THIS_IN_INITIALIZER_LIST(translate_helper_(this)),
@@ -692,8 +693,6 @@ void RenderView::OnMessageReceived(const IPC::Message& message) {
OnDisassociateFromPopupCount)
IPC_MESSAGE_HANDLER(ViewMsg_AutoFillSuggestionsReturned,
OnAutoFillSuggestionsReturned)
- IPC_MESSAGE_HANDLER(ViewMsg_AutocompleteSuggestionsReturned,
- OnAutocompleteSuggestionsReturned)
IPC_MESSAGE_HANDLER(ViewMsg_AutoFillFormDataFilled,
OnAutoFillFormDataFilled)
IPC_MESSAGE_HANDLER(ViewMsg_AllowScriptToClose,
@@ -1522,32 +1521,37 @@ void RenderView::OnAutoFillSuggestionsReturned(
if (webview() && query_id == autofill_query_id_) {
std::vector<string16> v(values);
std::vector<string16> l(labels);
- int separator_index = v.size();
+ int separator_index = -1;
// The form has been auto-filled, so give the user the chance to clear the
- // form.
+ // form. Append the 'Clear form' menu item.
if (form_manager_.FormWithNodeIsAutoFilled(autofill_query_node_)) {
- v.push_back(l10n_util::GetStringUTF16(
- IDS_AUTOFILL_CLEAR_FORM_MENU_ITEM));
+ v.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_CLEAR_FORM_MENU_ITEM));
l.push_back(string16());
+ suggestions_clear_index_ = v.size() - 1;
+ separator_index = values.size();
}
- // Append the 'AutoFill Options...' menu item.
- v.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_OPTIONS));
- l.push_back(string16());
- suggestions_count_ = v.size();
- webview()->applyAutoFillSuggestions(
- autofill_query_node_, v, l, separator_index);
- }
-}
+ size_t labeled_item_count = 0;
+ for (size_t i = 0; i < l.size(); ++i) {
+ if (!l[i].empty())
+ labeled_item_count++;
+ }
-void RenderView::OnAutocompleteSuggestionsReturned(
- int query_id,
- const std::vector<string16>& suggestions,
- int default_suggestion_index) {
- if (webview() && query_id == autofill_query_id_) {
- webview()->applyAutocompleteSuggestions(
- autofill_query_node_, suggestions, default_suggestion_index);
+ // Only include "AutoFill Options" special menu item if we have labeled
+ // items.
+ if (labeled_item_count > 0) {
+ // Append the 'AutoFill Options...' menu item.
+ v.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_OPTIONS));
+ l.push_back(string16());
+ suggestions_options_index_ = v.size() - 1;
+ separator_index = values.size();
+ }
+
+ // Send to WebKit for display.
+ if (!v.empty())
+ webview()->applyAutoFillSuggestions(
+ autofill_query_node_, v, l, separator_index);
}
}
@@ -2108,28 +2112,32 @@ void RenderView::didAcceptAutoFillSuggestion(const WebKit::WebNode& node,
const WebKit::WebString& value,
const WebKit::WebString& label,
unsigned index) {
- DCHECK_NE(0U, suggestions_count_);
-
- if (index == suggestions_count_ - 1) {
- // User selected 'AutoFill Options...'.
+ if (suggestions_options_index_ != -1 &&
+ index == static_cast<unsigned>(suggestions_options_index_)) {
+ // User selected 'AutoFill Options'.
Send(new ViewHostMsg_ShowAutoFillDialog(routing_id_));
- } else if (form_manager_.FormWithNodeIsAutoFilled(node) &&
- index == suggestions_count_ - 2) {
+ } else if (suggestions_clear_index_ != -1 &&
+ index == static_cast<unsigned>(suggestions_clear_index_)) {
+ // User selected 'Clear form'.
// The form has been auto-filled, so give the user the chance to clear the
// form.
form_manager_.ClearFormWithNode(node);
- } else if (form_manager_.FormWithNodeIsAutoFilled(node)) {
- // Fill a specific field value.
- // Cast away const'ness in this case where we're filling the element
- // directly.
+ } else if (form_manager_.FormWithNodeIsAutoFilled(node) || label.isEmpty()) {
+ // User selected an unlabeled menu item, so we fill directly.
WebInputElement element = node.toConst<WebInputElement>();
element.setValue(value);
+
+ WebFrame* webframe = node.document().frame();
+ if (webframe) {
+ webframe->notifiyPasswordListenerOfAutocomplete(element);
+ }
} else {
// Fill the values for the whole form.
QueryAutoFillFormData(node, value, label, AUTOFILL_FILL);
}
- suggestions_count_ = 0;
+ suggestions_clear_index_ = -1;
+ suggestions_options_index_ = -1;
}
void RenderView::didSelectAutoFillSuggestion(const WebKit::WebNode& node,
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index c52fe51..30af943 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -1157,8 +1157,11 @@ class RenderView : public RenderWidget,
// The action to take when receiving AutoFill data from the AutoFillManager.
AutoFillAction autofill_action_;
- // The number of suggestions sent to the AutoFill popup in WebKit.
- size_t suggestions_count_;
+ // The menu index of the "Clear" menu item.
+ int suggestions_clear_index_;
+
+ // The menu index of the "AutoFill options..." menu item.
+ int suggestions_options_index_;
// Plugins -------------------------------------------------------------------
diff --git a/chrome/renderer/render_view_unittest.cc b/chrome/renderer/render_view_unittest.cc
index b914553..9b9640e 100644
--- a/chrome/renderer/render_view_unittest.cc
+++ b/chrome/renderer/render_view_unittest.cc
@@ -987,11 +987,13 @@ TEST_F(RenderViewTest, SendForms) {
WebDocument document = web_frame->document();
WebInputElement firstname =
document.getElementById("firstname").to<WebInputElement>();
- // didAcceptAutoFillSuggestions expects a non-zero number of suggestions.
- view_->suggestions_count_ = 1;
+
+ // Accept suggestion that contains a label. Labeled items indicate AutoFill
+ // as opposed to Autocomplete. We're testing this distinction below with
+ // the |ViewHostMsg_FillAutoFillFormData::ID| message.
view_->didAcceptAutoFillSuggestion(firstname,
- WebKit::WebString(),
- WebKit::WebString(),
+ WebKit::WebString::fromUTF8("Johnny"),
+ WebKit::WebString::fromUTF8("Home"),
-1);
ProcessPendingMessages();
@@ -1065,8 +1067,6 @@ TEST_F(RenderViewTest, FillFormElement) {
WebInputElement middlename =
document.getElementById("middlename").to<WebInputElement>();
middlename.setAutofilled(true);
- // didAcceptAutoFillSuggestions expects a non-zero number of suggestions.
- view_->suggestions_count_ = 4;
// Accept a suggestion in a form that has been auto-filled. This triggers
// the direct filling of the firstname element with value parameter.
diff --git a/webkit/glue/webpasswordautocompletelistener_impl.cc b/webkit/glue/webpasswordautocompletelistener_impl.cc
index 8791c80..a1ea755 100644
--- a/webkit/glue/webpasswordautocompletelistener_impl.cc
+++ b/webkit/glue/webpasswordautocompletelistener_impl.cc
@@ -54,12 +54,19 @@ void WebInputElementDelegate::SetSelectionRange(size_t start, size_t end) {
}
void WebInputElementDelegate::RefreshAutofillPopup(
- const std::vector<string16>& suggestions,
- int default_suggestion_index) {
+ const std::vector<string16>& suggestions) {
WebView* webview = element_.document().frame()->view();
- if (webview)
- webview->applyAutocompleteSuggestions(element_, suggestions,
- default_suggestion_index);
+ if (webview) {
+ std::vector<string16> names;
+ std::vector<string16> labels;
+
+ for (size_t i = 0; i < suggestions.size(); ++i) {
+ names.push_back(suggestions[i]);
+ labels.push_back(string16());
+ }
+
+ webview->applyAutoFillSuggestions(element_, names, labels, -1);
+ }
}
WebPasswordAutocompleteListenerImpl::WebPasswordAutocompleteListenerImpl(
@@ -151,7 +158,7 @@ bool WebPasswordAutocompleteListenerImpl::showSuggestionPopup(
if (suggestions.empty())
return false;
- username_delegate_->RefreshAutofillPopup(suggestions, -1);
+ username_delegate_->RefreshAutofillPopup(suggestions);
return true;
}
diff --git a/webkit/glue/webpasswordautocompletelistener_impl.h b/webkit/glue/webpasswordautocompletelistener_impl.h
index 0c37b89e..ca4604b 100644
--- a/webkit/glue/webpasswordautocompletelistener_impl.h
+++ b/webkit/glue/webpasswordautocompletelistener_impl.h
@@ -34,8 +34,7 @@ class WebInputElementDelegate {
virtual bool IsAutofilled() const;
virtual void SetAutofilled(bool autofilled);
virtual void SetSelectionRange(size_t start, size_t end);
- virtual void RefreshAutofillPopup(const std::vector<string16>& suggestions,
- int default_suggestion_index);
+ virtual void RefreshAutofillPopup(const std::vector<string16>& suggestions);
private:
// The underlying DOM element we're wrapping.