diff options
author | csharp@chromium.org <csharp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-08 21:24:08 +0000 |
---|---|---|
committer | csharp@chromium.org <csharp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-08 21:24:08 +0000 |
commit | 5c8de6b907f1bbc25f76b9a1062b5fd9df0735fb (patch) | |
tree | 4d28cc605a2a37a626b471502f26291a4b0dfd16 /chrome | |
parent | 59ac148b23ebd8aa24eb4319c8a15133b90719ed (diff) | |
download | chromium_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.cc | 227 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_external_delegate.h | 36 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_external_delegate_unittest.cc | 99 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_manager.cc | 14 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_manager.h | 4 | ||||
-rw-r--r-- | chrome/common/autofill_messages.h | 15 | ||||
-rw-r--r-- | chrome/renderer/autofill/autofill_agent.cc | 59 | ||||
-rw-r--r-- | chrome/renderer/autofill/autofill_agent.h | 1 |
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 |