summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorcsharp@chromium.org <csharp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-08 21:24:08 +0000
committercsharp@chromium.org <csharp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-08 21:24:08 +0000
commit5c8de6b907f1bbc25f76b9a1062b5fd9df0735fb (patch)
tree4d28cc605a2a37a626b471502f26291a4b0dfd16 /chrome
parent59ac148b23ebd8aa24eb4319c8a15133b90719ed (diff)
downloadchromium_src-5c8de6b907f1bbc25f76b9a1062b5fd9df0735fb.zip
chromium_src-5c8de6b907f1bbc25f76b9a1062b5fd9df0735fb.tar.gz
chromium_src-5c8de6b907f1bbc25f76b9a1062b5fd9df0735fb.tar.bz2
Add Datalist Support to New Autofill UI
Show Datalist elements in the new Autofill UI, properly separated from the other data and fully selectable. BUG=51644 TEST=The datalist elements can be selected like normal autofill elements and unit tests pass. Review URL: https://chromiumcodereview.appspot.com/10443084 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@141287 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/autofill/autofill_external_delegate.cc227
-rw-r--r--chrome/browser/autofill/autofill_external_delegate.h36
-rw-r--r--chrome/browser/autofill/autofill_external_delegate_unittest.cc99
-rw-r--r--chrome/browser/autofill/autofill_manager.cc14
-rw-r--r--chrome/browser/autofill/autofill_manager.h4
-rw-r--r--chrome/common/autofill_messages.h15
-rw-r--r--chrome/renderer/autofill/autofill_agent.cc59
-rw-r--r--chrome/renderer/autofill/autofill_agent.h1
8 files changed, 366 insertions, 89 deletions
diff --git a/chrome/browser/autofill/autofill_external_delegate.cc b/chrome/browser/autofill/autofill_external_delegate.cc
index 436e6577..ada423f 100644
--- a/chrome/browser/autofill/autofill_external_delegate.cc
+++ b/chrome/browser/autofill/autofill_external_delegate.cc
@@ -30,22 +30,16 @@ AutofillExternalDelegate::AutofillExternalDelegate(
tab_contents ? tab_contents->web_contents() : NULL),
autofill_query_id_(0),
display_warning_if_disabled_(false),
- has_shown_autofill_popup_for_current_edit_(false) {
+ has_shown_autofill_popup_for_current_edit_(false),
+ popup_visible_(false) {
}
void AutofillExternalDelegate::SelectAutofillSuggestionAtIndex(int unique_id) {
- if (unique_id == WebAutofillClient::MenuItemIDAutofillOptions ||
- unique_id == WebAutofillClient::MenuItemIDClearForm ||
- unique_id == WebAutofillClient::MenuItemIDSeparator ||
- unique_id == WebAutofillClient::MenuItemIDWarningMessage)
- return;
-
ClearPreviewedForm();
- if (unique_id == WebAutofillClient::MenuItemIDPasswordEntry)
- return;
-
- FillAutofillFormData(unique_id, true);
+ // Only preview the data if it is a profile.
+ if (unique_id > 0)
+ FillAutofillFormData(unique_id, true);
}
void AutofillExternalDelegate::OnQuery(int query_id,
@@ -63,49 +57,25 @@ void AutofillExternalDelegate::OnQuery(int query_id,
void AutofillExternalDelegate::OnSuggestionsReturned(
int query_id,
- const std::vector<string16>& values,
- const std::vector<string16>& labels,
- const std::vector<string16>& icons,
- const std::vector<int>& unique_ids) {
+ const std::vector<string16>& autofill_values,
+ const std::vector<string16>& autofill_labels,
+ const std::vector<string16>& autofill_icons,
+ const std::vector<int>& autofill_unique_ids) {
if (query_id != autofill_query_id_)
return;
- if (values.empty()) {
- // No suggestions, any popup currently showing is obsolete.
- HideAutofillPopup();
- return;
- }
-
- std::vector<string16> v(values);
- std::vector<string16> l(labels);
- std::vector<string16> i(icons);
- std::vector<int> ids(unique_ids);
+ std::vector<string16> values(autofill_values);
+ std::vector<string16> labels(autofill_labels);
+ std::vector<string16> icons(autofill_icons);
+ std::vector<int> ids(autofill_unique_ids);
// Add a separator to go between the values and menu items.
- v.push_back(string16());
- l.push_back(string16());
- i.push_back(string16());
+ values.push_back(string16());
+ labels.push_back(string16());
+ icons.push_back(string16());
ids.push_back(WebAutofillClient::MenuItemIDSeparator);
- DCHECK_GT(ids.size(), 0U);
- if (!autofill_query_field_.should_autocomplete) {
- // If autofill is disabled and we had suggestions, show a warning instead.
- v.assign(1, l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_FORM_DISABLED));
- l.assign(1, string16());
- i.assign(1, string16());
- ids.assign(1, WebAutofillClient::MenuItemIDWarningMessage);
- } else if (ids[0] < 0 && ids.size() > 1) {
- // If we received a warning instead of suggestions from autofill but regular
- // suggestions from autocomplete, don't show the autofill warning.
- v.erase(v.begin());
- l.erase(l.begin());
- i.erase(i.begin());
- ids.erase(ids.begin());
- }
-
- // If we were about to show a warning and we shouldn't, don't.
- if (ids[0] < 0 && !display_warning_if_disabled_)
- return;
+ ApplyAutofillWarnings(&values, &labels, &icons, &ids);
// Only include "Autofill Options" special menu item if we have Autofill
// items, identified by |unique_ids| having at least one valid value.
@@ -117,38 +87,34 @@ void AutofillExternalDelegate::OnSuggestionsReturned(
}
}
- // The form has been auto-filled, so give the user the chance to clear the
- // form. Append the 'Clear form' menu item.
- if (has_autofill_item && autofill_query_field_.is_autofilled) {
- v.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_CLEAR_FORM_MENU_ITEM));
- l.push_back(string16());
- i.push_back(string16());
- ids.push_back(WebAutofillClient::MenuItemIDClearForm);
- }
-
- if (has_autofill_item) {
- // Append the 'Chrome Autofill options' menu item;
- v.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_OPTIONS_POPUP));
- l.push_back(string16());
- i.push_back(string16());
- ids.push_back(WebAutofillClient::MenuItemIDAutofillOptions);
- }
+ if (has_autofill_item)
+ ApplyAutofillOptions(&values, &labels, &icons, &ids);
// Remove the separator if it is the last element.
- if (*(ids.rbegin()) == WebAutofillClient::MenuItemIDSeparator) {
- v.pop_back();
- l.pop_back();
- i.pop_back();
+ if (ids.back() == WebAutofillClient::MenuItemIDSeparator) {
+ values.pop_back();
+ labels.pop_back();
+ icons.pop_back();
ids.pop_back();
}
+ InsertDataListValues(&values, &labels, &icons, &ids);
+
+ if (values.empty()) {
+ // No suggestions, any popup currently showing is obsolete.
+ HideAutofillPopup();
+ return;
+ }
+
// Send to display.
- if (!v.empty() && autofill_query_field_.is_focusable)
- ApplyAutofillSuggestions(v, l, i, ids);
+ if (autofill_query_field_.is_focusable) {
+ popup_visible_ = true;
+ ApplyAutofillSuggestions(values, labels, icons, ids);
- tab_contents_->autofill_manager()->OnDidShowAutofillSuggestions(
- has_autofill_item && !has_shown_autofill_popup_for_current_edit_);
- has_shown_autofill_popup_for_current_edit_ |= has_autofill_item;
+ tab_contents_->autofill_manager()->OnDidShowAutofillSuggestions(
+ has_autofill_item && !has_shown_autofill_popup_for_current_edit_);
+ has_shown_autofill_popup_for_current_edit_ |= has_autofill_item;
+ }
}
void AutofillExternalDelegate::OnShowPasswordSuggestions(
@@ -170,6 +136,22 @@ void AutofillExternalDelegate::OnShowPasswordSuggestions(
ApplyAutofillSuggestions(suggestions, empty, empty, password_ids);
}
+void AutofillExternalDelegate::SetCurrentDataListValues(
+ const std::vector<string16>& data_list_values,
+ const std::vector<string16>& data_list_labels,
+ const std::vector<string16>& data_list_icons,
+ const std::vector<int>& data_list_unique_ids) {
+ // TODO(csharp): Modify the code to allow the data list values to change
+ // even if the popup is visible.
+ // http://crbug.com/131003
+ if (!popup_visible_) {
+ data_list_values_ = data_list_values;
+ data_list_labels_ = data_list_labels;
+ data_list_icons_ = data_list_icons;
+ data_list_unique_ids_ = data_list_unique_ids;
+ }
+}
+
void AutofillExternalDelegate::RemoveAutocompleteEntry(const string16& value) {
if (tab_contents_) {
tab_contents_->autocomplete_history_manager()->
@@ -197,21 +179,25 @@ bool AutofillExternalDelegate::DidAcceptAutofillSuggestions(
if (unique_id == WebAutofillClient::MenuItemIDWarningMessage)
return false;
+ RenderViewHost* host =
+ tab_contents_->web_contents()->GetRenderViewHost();
+
if (unique_id == WebAutofillClient::MenuItemIDAutofillOptions) {
// User selected 'Autofill Options'.
autofill_manager_->OnShowAutofillDialog();
} else if (unique_id == WebAutofillClient::MenuItemIDClearForm) {
// User selected 'Clear form'.
- RenderViewHost* host = tab_contents_->web_contents()->GetRenderViewHost();
host->Send(new AutofillMsg_ClearForm(host->GetRoutingID()));
} else if (unique_id == WebAutofillClient::MenuItemIDPasswordEntry &&
password_autofill_manager_.DidAcceptAutofillSuggestion(
autofill_query_field_, value)) {
// DidAcceptAutofillSuggestion has already handled the work to fill in
// the page as required.
+ } else if (unique_id == WebAutofillClient::MenuItemIDDataListEntry) {
+ host->Send(new AutofillMsg_AcceptDataListSuggestion(host->GetRoutingID(),
+ value));
} else if (unique_id == WebAutofillClient::MenuItemIDAutocompleteEntry) {
// User selected an Autocomplete, so we fill directly.
- RenderViewHost* host = tab_contents_->web_contents()->GetRenderViewHost();
host->Send(new AutofillMsg_SetNodeText(
host->GetRoutingID(),
value));
@@ -230,6 +216,8 @@ void AutofillExternalDelegate::ClearPreviewedForm() {
}
void AutofillExternalDelegate::HideAutofillPopup() {
+ popup_visible_ = false;
+
HideAutofillPopupInternal();
}
@@ -264,6 +252,97 @@ void AutofillExternalDelegate::FillAutofillFormData(int unique_id,
unique_id);
}
+void AutofillExternalDelegate::ApplyAutofillWarnings(
+ std::vector<string16>* autofill_values,
+ std::vector<string16>* autofill_labels,
+ std::vector<string16>* autofill_icons,
+ std::vector<int>* autofill_unique_ids) {
+ if (!autofill_query_field_.should_autocomplete) {
+ // If autofill is disabled and we had suggestions, show a warning instead.
+ autofill_values->assign(
+ 1, l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_FORM_DISABLED));
+ autofill_labels->assign(1, string16());
+ autofill_icons->assign(1, string16());
+ autofill_unique_ids->assign(1, WebAutofillClient::MenuItemIDWarningMessage);
+ } else if (autofill_unique_ids->size() > 1 &&
+ (*autofill_unique_ids)[0] ==
+ WebAutofillClient::MenuItemIDWarningMessage) {
+ // If we received a warning instead of suggestions from autofill but regular
+ // suggestions from autocomplete, don't show the autofill warning.
+ autofill_values->erase(autofill_values->begin());
+ autofill_labels->erase(autofill_labels->begin());
+ autofill_icons->erase(autofill_icons->begin());
+ autofill_unique_ids->erase(autofill_unique_ids->begin());
+ }
+
+ // If we were about to show a warning and we shouldn't, don't.
+ if (!autofill_unique_ids->empty() &&
+ (*autofill_unique_ids)[0] ==
+ WebAutofillClient::MenuItemIDWarningMessage &&
+ !display_warning_if_disabled_) {
+ autofill_values->clear();
+ autofill_labels->clear();
+ autofill_icons->clear();
+ autofill_unique_ids->clear();
+ }
+}
+
+void AutofillExternalDelegate::ApplyAutofillOptions(
+ std::vector<string16>* autofill_values,
+ std::vector<string16>* autofill_labels,
+ std::vector<string16>* autofill_icons,
+ std::vector<int>* autofill_unique_ids) {
+ // The form has been auto-filled, so give the user the chance to clear the
+ // form. Append the 'Clear form' menu item.
+ if (autofill_query_field_.is_autofilled) {
+ autofill_values->push_back(
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_CLEAR_FORM_MENU_ITEM));
+ autofill_labels->push_back(string16());
+ autofill_icons->push_back(string16());
+ autofill_unique_ids->push_back(WebAutofillClient::MenuItemIDClearForm);
+ }
+
+ // Append the 'Chrome Autofill options' menu item;
+ autofill_values->push_back(
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_OPTIONS_POPUP));
+ autofill_labels->push_back(string16());
+ autofill_icons->push_back(string16());
+ autofill_unique_ids->push_back(WebAutofillClient::MenuItemIDAutofillOptions);
+}
+
+void AutofillExternalDelegate::InsertDataListValues(
+ std::vector<string16>* autofill_values,
+ std::vector<string16>* autofill_labels,
+ std::vector<string16>* autofill_icons,
+ std::vector<int>* autofill_unique_ids) {
+ if (data_list_values_.empty())
+ return;
+
+ // Insert the separator between the datalist and Autofill values (if there
+ // are any).
+ if (!autofill_values->empty()) {
+ autofill_values->insert(autofill_values->begin(), string16());
+ autofill_labels->insert(autofill_labels->begin(), string16());
+ autofill_icons->insert(autofill_icons->begin(), string16());
+ autofill_unique_ids->insert(autofill_unique_ids->begin(),
+ WebAutofillClient::MenuItemIDSeparator);
+ }
+
+ // Insert the datalist elements.
+ autofill_values->insert(autofill_values->begin(),
+ data_list_values_.begin(),
+ data_list_values_.end());
+ autofill_labels->insert(autofill_labels->begin(),
+ data_list_labels_.begin(),
+ data_list_labels_.end());
+ autofill_icons->insert(autofill_icons->begin(),
+ data_list_icons_.begin(),
+ data_list_icons_.end());
+ autofill_unique_ids->insert(autofill_unique_ids->begin(),
+ data_list_unique_ids_.begin(),
+ data_list_unique_ids_.end());
+}
+
// Add a "!defined(OS_YOUROS) for each platform that implements this
// in an autofill_external_delegate_YOUROS.cc. Currently there are
// none, so all platforms use the default.
diff --git a/chrome/browser/autofill/autofill_external_delegate.h b/chrome/browser/autofill/autofill_external_delegate.h
index f4e698a..e21f123 100644
--- a/chrome/browser/autofill/autofill_external_delegate.h
+++ b/chrome/browser/autofill/autofill_external_delegate.h
@@ -63,6 +63,12 @@ class AutofillExternalDelegate {
const webkit::forms::FormField& field,
const gfx::Rect& bounds);
+ // Set the data list value associated with the current field.
+ void SetCurrentDataListValues(const std::vector<string16>& autofill_values,
+ const std::vector<string16>& autofill_labels,
+ const std::vector<string16>& autofill_icons,
+ const std::vector<int>& autofill_unique_ids);
+
// Remove the given Autocomplete entry from the DB.
virtual void RemoveAutocompleteEntry(const string16& value);
@@ -135,6 +141,27 @@ class AutofillExternalDelegate {
// this data.
void FillAutofillFormData(int unique_id, bool is_preview);
+ // Handle applying any Autofill warnings to the Autofill popup.
+ void ApplyAutofillWarnings(std::vector<string16>* autofill_values,
+ std::vector<string16>* autofill_labels,
+ std::vector<string16>* autofill_icons,
+ std::vector<int>* autofill_unique_ids);
+
+ // Handle applying any Autofill option listings to the Autofill popup.
+ // This function should only get called when there is at least one
+ // multi-field suggestion in the list of suggestions.
+ void ApplyAutofillOptions(std::vector<string16>* autofill_values,
+ std::vector<string16>* autofill_labels,
+ std::vector<string16>* autofill_icons,
+ std::vector<int>* autofill_unique_ids);
+
+ // Insert the data list values at the start of the given list, including
+ // any required separators.
+ void InsertDataListValues(std::vector<string16>* autofill_values,
+ std::vector<string16>* autofill_labels,
+ std::vector<string16>* autofill_icons,
+ std::vector<int>* autofill_unique_ids);
+
TabContents* tab_contents_; // weak; owns me.
AutofillManager* autofill_manager_; // weak.
@@ -156,6 +183,15 @@ class AutofillExternalDelegate {
// currently editing? Used to keep track of state for metrics logging.
bool has_shown_autofill_popup_for_current_edit_;
+ // Used to indicate if a popup is currently being shown or not.
+ bool popup_visible_;
+
+ // The current data list values.
+ std::vector<string16> data_list_values_;
+ std::vector<string16> data_list_labels_;
+ std::vector<string16> data_list_icons_;
+ std::vector<int> data_list_unique_ids_;
+
DISALLOW_COPY_AND_ASSIGN(AutofillExternalDelegate);
};
diff --git a/chrome/browser/autofill/autofill_external_delegate_unittest.cc b/chrome/browser/autofill/autofill_external_delegate_unittest.cc
index 8b7696d..0e6183d 100644
--- a/chrome/browser/autofill/autofill_external_delegate_unittest.cc
+++ b/chrome/browser/autofill/autofill_external_delegate_unittest.cc
@@ -27,6 +27,12 @@ using WebKit::WebAutofillClient;
namespace {
+// A constant value to use as the Autofill query ID.
+const int kQueryId = 5;
+
+// A constant value to use as an Autofill profile ID.
+const int kAutofillProfileId = 1;
+
class MockAutofillExternalDelegate : public TestAutofillExternalDelegate {
public:
MockAutofillExternalDelegate(TabContents* tab_contents,
@@ -88,6 +94,22 @@ class AutofillExternalDelegateUnitTest : public TabContentsTestHarness {
}
protected:
+ // Set up the expectation for a platform specific OnQuery call and then
+ // execute it with the given QueryId.
+ void IssueOnQuery(int query_id) {
+ const FormData form;
+ FormField field;
+ field.is_focusable = true;
+ field.should_autocomplete = true;
+ const gfx::Rect bounds;
+
+ EXPECT_CALL(*external_delegate_,
+ OnQueryPlatformSpecific(query_id, form, field, bounds));
+
+ // This should call OnQueryPlatform specific.
+ external_delegate_->OnQuery(query_id, form, field, bounds, false);
+ }
+
scoped_refptr<MockAutofillManager> autofill_manager_;
scoped_ptr<MockAutofillExternalDelegate> external_delegate_;
@@ -99,26 +121,21 @@ class AutofillExternalDelegateUnitTest : public TabContentsTestHarness {
// Test that our external delegate called the virtual methods at the right time.
TEST_F(AutofillExternalDelegateUnitTest, TestExternalDelegateVirtualCalls) {
- const int kQueryId = 5;
- const FormData form;
- FormField field;
- field.is_focusable = true;
- field.should_autocomplete = true;
- const gfx::Rect bounds;
+ IssueOnQuery(kQueryId);
+ // The enums must be cast to ints to prevent compile errors on linux_rel.
EXPECT_CALL(*external_delegate_,
- OnQueryPlatformSpecific(kQueryId, form, field, bounds));
-
- // This should call OnQueryPlatform specific.
- external_delegate_->OnQuery(kQueryId, form, field, bounds, false);
-
- EXPECT_CALL(*external_delegate_, ApplyAutofillSuggestions(_, _, _, _));
+ ApplyAutofillSuggestions(_, _, _, testing::ElementsAre(
+ kAutofillProfileId,
+ static_cast<int>(WebAutofillClient::MenuItemIDSeparator),
+ static_cast<int>(
+ WebAutofillClient::MenuItemIDAutofillOptions))));
// This should call ApplyAutofillSuggestions.
std::vector<string16> autofill_item;
autofill_item.push_back(string16());
std::vector<int> autofill_ids;
- autofill_ids.push_back(1);
+ autofill_ids.push_back(kAutofillProfileId);
external_delegate_->OnSuggestionsReturned(kQueryId,
autofill_item,
autofill_item,
@@ -137,11 +154,67 @@ TEST_F(AutofillExternalDelegateUnitTest, TestExternalDelegateVirtualCalls) {
autofill_ids[0], 0);
}
+// Test that data list elements for a node will appear in the Autofill popup.
+TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateDataList) {
+ IssueOnQuery(kQueryId);
+
+ std::vector<string16> data_list_items;
+ data_list_items.push_back(string16());
+ std::vector<int> data_list_ids;
+ data_list_ids.push_back(WebAutofillClient::MenuItemIDDataListEntry);
+
+ external_delegate_->SetCurrentDataListValues(data_list_items,
+ data_list_items,
+ data_list_items,
+ data_list_ids);
+
+ // The enums must be cast to ints to prevent compile errors on linux_rel.
+ EXPECT_CALL(*external_delegate_,
+ ApplyAutofillSuggestions(
+ _, _, _, testing::ElementsAre(
+ static_cast<int>(
+ WebAutofillClient::MenuItemIDDataListEntry),
+ static_cast<int>(WebAutofillClient::MenuItemIDSeparator),
+ kAutofillProfileId,
+ static_cast<int>(WebAutofillClient::MenuItemIDSeparator),
+ static_cast<int>(
+ WebAutofillClient::MenuItemIDAutofillOptions))));
+
+ // This should call ApplyAutofillSuggestions.
+ std::vector<string16> autofill_item;
+ autofill_item.push_back(string16());
+ std::vector<int> autofill_ids;
+ autofill_ids.push_back(kAutofillProfileId);
+ external_delegate_->OnSuggestionsReturned(kQueryId,
+ autofill_item,
+ autofill_item,
+ autofill_item,
+ autofill_ids);
+
+ // Try calling OnSuggestionsReturned with no Autofill values and ensure
+ // the datalist items are still shown.
+ // The enum must be cast to an int to prevent compile errors on linux_rel.
+ EXPECT_CALL(*external_delegate_,
+ ApplyAutofillSuggestions(
+ _, _, _, testing::ElementsAre(
+ static_cast<int>(
+ WebAutofillClient::MenuItemIDDataListEntry))));
+
+ autofill_item = std::vector<string16>();
+ autofill_ids = std::vector<int>();
+ external_delegate_->OnSuggestionsReturned(kQueryId,
+ autofill_item,
+ autofill_item,
+ autofill_item,
+ autofill_ids);
+}
+
// Test that the Autofill delegate doesn't try and fill a form with a
// negative unique id.
TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateInvalidUniqueId) {
// Ensure it doesn't try to preview the negative id.
EXPECT_CALL(*autofill_manager_, OnFillAutofillFormData(_, _, _, _)).Times(0);
+ EXPECT_CALL(*external_delegate_, ClearPreviewedForm()).Times(1);
external_delegate_->SelectAutofillSuggestionAtIndex(-1);
// Ensure it doesn't try to fill the form in with the negative id.
diff --git a/chrome/browser/autofill/autofill_manager.cc b/chrome/browser/autofill/autofill_manager.cc
index fbabdbf..107fe64 100644
--- a/chrome/browser/autofill/autofill_manager.cc
+++ b/chrome/browser/autofill/autofill_manager.cc
@@ -343,6 +343,8 @@ bool AutofillManager::OnMessageReceived(const IPC::Message& message) {
OnAddPasswordFormMapping)
IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowPasswordSuggestions,
OnShowPasswordSuggestions)
+ IPC_MESSAGE_HANDLER(AutofillHostMsg_SetDataList,
+ OnSetDataList)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -771,6 +773,18 @@ void AutofillManager::OnShowPasswordSuggestions(
external_delegate_->OnShowPasswordSuggestions(suggestions, field, bounds);
}
+void AutofillManager::OnSetDataList(const std::vector<string16>& values,
+ const std::vector<string16>& labels,
+ const std::vector<string16>& icons,
+ const std::vector<int>& unique_ids) {
+ if (external_delegate_) {
+ external_delegate_->SetCurrentDataListValues(values,
+ labels,
+ icons,
+ unique_ids);
+ }
+}
+
void AutofillManager::OnLoadedServerPredictions(
const std::string& response_xml) {
// Parse and store the server predictions.
diff --git a/chrome/browser/autofill/autofill_manager.h b/chrome/browser/autofill/autofill_manager.h
index 0776c3e..f03fa6b 100644
--- a/chrome/browser/autofill/autofill_manager.h
+++ b/chrome/browser/autofill/autofill_manager.h
@@ -219,6 +219,10 @@ class AutofillManager : public content::NotificationObserver,
void OnShowPasswordSuggestions(const webkit::forms::FormField& field,
const gfx::Rect& bounds,
const std::vector<string16>& suggestions);
+ void OnSetDataList(const std::vector<string16>& values,
+ const std::vector<string16>& labels,
+ const std::vector<string16>& icons,
+ const std::vector<int>& unique_ids);
// Fills |host| with the RenderViewHost for this tab.
// Returns false if Autofill is disabled or if the host is unavailable.
diff --git a/chrome/common/autofill_messages.h b/chrome/common/autofill_messages.h
index 5924ba3..636a15b 100644
--- a/chrome/common/autofill_messages.h
+++ b/chrome/common/autofill_messages.h
@@ -109,9 +109,13 @@ IPC_MESSAGE_ROUTED0(AutofillMsg_SetAutofillActionPreview)
// Tells the renderer that the Autofill previewed form should be cleared.
IPC_MESSAGE_ROUTED0(AutofillMsg_ClearPreviewedForm)
-// Sets the currently selected nodes value.
+// Sets the currently selected node's value.
IPC_MESSAGE_ROUTED1(AutofillMsg_SetNodeText,
- string16)
+ string16 /* new node text */)
+
+// Sets the currently selected node's value to be the given data list value.
+IPC_MESSAGE_ROUTED1(AutofillMsg_AcceptDataListSuggestion,
+ string16 /* accepted data list value */)
// Tells the renderer to populate the correct password fields with this
// generated password.
@@ -216,3 +220,10 @@ IPC_MESSAGE_ROUTED3(AutofillHostMsg_ShowPasswordSuggestions,
webkit::forms::FormField /* the form field */,
gfx::Rect /* input field bounds, window-relative */,
std::vector<string16> /* suggestions */)
+
+// Inform browser of data list values for the curent field.
+IPC_MESSAGE_ROUTED4(AutofillHostMsg_SetDataList,
+ std::vector<string16> /* values */,
+ std::vector<string16> /* labels */,
+ std::vector<string16> /* icons */,
+ std::vector<int> /* unique ids */)
diff --git a/chrome/renderer/autofill/autofill_agent.cc b/chrome/renderer/autofill/autofill_agent.cc
index 2442899..a86a213 100644
--- a/chrome/renderer/autofill/autofill_agent.cc
+++ b/chrome/renderer/autofill/autofill_agent.cc
@@ -52,6 +52,10 @@ namespace {
// (so to avoid sending long strings through IPC).
const size_t kMaximumTextSizeForAutofill = 1000;
+// The maximum number of data list elements to send to the browser process
+// via IPC (to prevent long IPC messages).
+const size_t kMaximumDataListSizeForAutofill = 30;
+
void AppendDataListSuggestions(const WebKit::WebInputElement& element,
std::vector<string16>* values,
std::vector<string16>* labels,
@@ -86,6 +90,33 @@ void AppendDataListSuggestions(const WebKit::WebInputElement& element,
}
}
+// Trim the vectors before sending them to the browser process to ensure we
+// don't send too much data through the IPC.
+void TrimDataListsForIPC(std::vector<string16>* values,
+ std::vector<string16>* labels,
+ std::vector<string16>* icons,
+ std::vector<int>* unique_ids) {
+ // Limit the size of the vectors.
+ if (values->size() > kMaximumDataListSizeForAutofill) {
+ values->resize(kMaximumDataListSizeForAutofill);
+ labels->resize(kMaximumDataListSizeForAutofill);
+ icons->resize(kMaximumDataListSizeForAutofill);
+ unique_ids->resize(kMaximumDataListSizeForAutofill);
+ }
+
+ // Limit the size of the strings in the vectors
+ for (size_t i = 0; i < values->size(); ++i) {
+ if ((*values)[i].length() > kMaximumTextSizeForAutofill)
+ (*values)[i].resize(kMaximumTextSizeForAutofill);
+
+ if ((*labels)[i].length() > kMaximumTextSizeForAutofill)
+ (*labels)[i].resize(kMaximumTextSizeForAutofill);
+
+ if ((*icons)[i].length() > kMaximumTextSizeForAutofill)
+ (*icons)[i].resize(kMaximumTextSizeForAutofill);
+ }
+}
+
} // namespace
namespace autofill {
@@ -126,6 +157,8 @@ bool AutofillAgent::OnMessageReceived(const IPC::Message& message) {
OnClearPreviewedForm)
IPC_MESSAGE_HANDLER(AutofillMsg_SetNodeText,
OnSetNodeText)
+ IPC_MESSAGE_HANDLER(AutofillMsg_AcceptDataListSuggestion,
+ OnAcceptDataListSuggestion)
IPC_MESSAGE_HANDLER(AutofillMsg_AcceptPasswordAutofillSuggestion,
OnAcceptPasswordAutofillSuggestion)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -529,6 +562,10 @@ void AutofillAgent::OnSetNodeText(const string16& value) {
SetNodeText(value, &element_);
}
+void AutofillAgent::OnAcceptDataListSuggestion(const string16& value) {
+ AcceptDataListSuggestion(value);
+}
+
void AutofillAgent::OnAcceptPasswordAutofillSuggestion(const string16& value) {
// We need to make sure this is handled here because the browser process
// skipped it handling because it believed it would be handled here. If it
@@ -600,6 +637,28 @@ void AutofillAgent::QueryAutofillSuggestions(const WebInputElement& element,
gfx::Rect bounding_box(element_.boundsInViewportSpace());
+ // Find the datalist values and send them to the browser process.
+ std::vector<string16> data_list_values;
+ std::vector<string16> data_list_labels;
+ std::vector<string16> data_list_icons;
+ std::vector<int> data_list_unique_ids;
+ AppendDataListSuggestions(element_,
+ &data_list_values,
+ &data_list_labels,
+ &data_list_icons,
+ &data_list_unique_ids);
+
+ TrimDataListsForIPC(&data_list_values,
+ &data_list_labels,
+ &data_list_icons,
+ &data_list_unique_ids);
+
+ Send(new AutofillHostMsg_SetDataList(routing_id(),
+ data_list_values,
+ data_list_labels,
+ data_list_icons,
+ data_list_unique_ids));
+
Send(new AutofillHostMsg_QueryFormFieldAutofill(routing_id(),
autofill_query_id_,
form,
diff --git a/chrome/renderer/autofill/autofill_agent.h b/chrome/renderer/autofill/autofill_agent.h
index 2c7fd55..245b639 100644
--- a/chrome/renderer/autofill/autofill_agent.h
+++ b/chrome/renderer/autofill/autofill_agent.h
@@ -112,6 +112,7 @@ class AutofillAgent : public content::RenderViewObserver,
void OnSetAutofillActionPreview();
void OnClearPreviewedForm();
void OnSetNodeText(const string16& value);
+ void OnAcceptDataListSuggestion(const string16& value);
void OnAcceptPasswordAutofillSuggestion(const string16& value);
// Called in a posted task by textFieldDidChange() to work-around a WebKit bug