summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorcsharp@chromium.org <csharp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-05 02:56:26 +0000
committercsharp@chromium.org <csharp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-05 02:56:26 +0000
commite7e834702fcd0237014e1808f72097e367ef8a63 (patch)
tree39f6a6f7a8d67ead2b3d2ad2f4c73b94b4167e49 /chrome/browser
parent634bc5d15ae1b294dcd29a17111a11e4228bd0ac (diff)
downloadchromium_src-e7e834702fcd0237014e1808f72097e367ef8a63.zip
chromium_src-e7e834702fcd0237014e1808f72097e367ef8a63.tar.gz
chromium_src-e7e834702fcd0237014e1808f72097e367ef8a63.tar.bz2
Add Password Autofill Manager to New Autofill
Copied over the password Autofill Manager functions from the renderer to the browser to allow the new Autofill UI to have access to them. BUG=51644 TEST= Review URL: http://codereview.chromium.org/9600038 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@130824 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/autofill/autofill_external_delegate.cc66
-rw-r--r--chrome/browser/autofill/autofill_external_delegate.h22
-rw-r--r--chrome/browser/autofill/autofill_external_delegate_gtk.cc5
-rw-r--r--chrome/browser/autofill/autofill_external_delegate_gtk.h1
-rw-r--r--chrome/browser/autofill/autofill_manager.cc27
-rw-r--r--chrome/browser/autofill/autofill_manager.h10
-rw-r--r--chrome/browser/autofill/password_autofill_manager.cc97
-rw-r--r--chrome/browser/autofill/password_autofill_manager.h81
-rw-r--r--chrome/browser/autofill/password_autofill_manager_unittest.cc94
-rw-r--r--chrome/browser/autofill/test_autofill_external_delegate.cc2
-rw-r--r--chrome/browser/autofill/test_autofill_external_delegate.h2
-rw-r--r--chrome/browser/password_manager_delegate_impl.cc6
12 files changed, 404 insertions, 9 deletions
diff --git a/chrome/browser/autofill/autofill_external_delegate.cc b/chrome/browser/autofill/autofill_external_delegate.cc
index 13f0b7d..ff94bd4 100644
--- a/chrome/browser/autofill/autofill_external_delegate.cc
+++ b/chrome/browser/autofill/autofill_external_delegate.cc
@@ -16,6 +16,16 @@
using content::RenderViewHost;
+namespace {
+
+// The value to give as the unique id for all warnings.
+const int kWarningId = -1;
+
+// The value to give as the unique id for all password entries.
+const int kPasswordEntryId = -2;
+
+} // namespace
+
AutofillExternalDelegate::~AutofillExternalDelegate() {
}
@@ -24,6 +34,8 @@ AutofillExternalDelegate::AutofillExternalDelegate(
AutofillManager* autofill_manager)
: tab_contents_wrapper_(tab_contents_wrapper),
autofill_manager_(autofill_manager),
+ password_autofill_manager_(
+ tab_contents_wrapper ? tab_contents_wrapper->web_contents() : NULL),
autofill_query_id_(0),
display_warning_if_disabled_(false),
has_shown_autofill_popup_for_current_edit_(false),
@@ -33,9 +45,13 @@ AutofillExternalDelegate::AutofillExternalDelegate(
void AutofillExternalDelegate::SelectAutofillSuggestionAtIndex(int unique_id,
int list_index) {
+ if (password_autofill_manager_.DidSelectAutofillSuggestion(
+ autofill_query_field_))
+ return;
+
if (list_index == suggestions_options_index_ ||
list_index == suggestions_clear_index_ ||
- unique_id == -1)
+ unique_id == kWarningId)
return;
FillAutofillFormData(unique_id, true);
@@ -81,7 +97,7 @@ void AutofillExternalDelegate::OnSuggestionsReturned(
v.assign(1, l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_FORM_DISABLED));
l.assign(1, string16());
i.assign(1, string16());
- ids.assign(1, -1);
+ ids.assign(1, kWarningId);
} 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.
@@ -136,6 +152,24 @@ void AutofillExternalDelegate::OnSuggestionsReturned(
has_shown_autofill_popup_for_current_edit_ |= has_autofill_item;
}
+void AutofillExternalDelegate::OnShowPasswordSuggestions(
+ const std::vector<string16>& suggestions,
+ const webkit::forms::FormField& field,
+ const gfx::Rect& bounds) {
+ autofill_query_field_ = field;
+
+ if (suggestions.empty()) {
+ HideAutofillPopup();
+ return;
+ }
+
+ SetBounds(bounds);
+
+ std::vector<string16> empty(suggestions.size());
+ std::vector<int> password_ids(suggestions.size(), kPasswordEntryId);
+ ApplyAutofillSuggestions(suggestions, empty, empty, password_ids, -1);
+}
+
void AutofillExternalDelegate::DidEndTextFieldEditing() {
has_shown_autofill_popup_for_current_edit_ = false;
}
@@ -145,13 +179,9 @@ bool AutofillExternalDelegate::DidAcceptAutofillSuggestions(
int unique_id,
unsigned index) {
// If the selected element is a warning we don't want to do anything.
- if (unique_id < 0)
+ if (unique_id == kWarningId)
return false;
- // TODO(csharp): Add the password autofill manager.
- // if (password_autofill_manager_->DidAcceptAutofillSuggestion(node, value))
- // return;
-
if (suggestions_options_index_ != -1 &&
index == static_cast<unsigned>(suggestions_options_index_)) {
// User selected 'Autofill Options'.
@@ -162,8 +192,12 @@ bool AutofillExternalDelegate::DidAcceptAutofillSuggestions(
RenderViewHost* host =
tab_contents_wrapper_->web_contents()->GetRenderViewHost();
host->Send(new AutofillMsg_ClearForm(host->GetRoutingID()));
+ } else if (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) {
- // User selected an Autocomplete entry, so we fill directly.
+ // User selected an Autocomplete, so we fill directly.
RenderViewHost* host =
tab_contents_wrapper_->web_contents()->GetRenderViewHost();
host->Send(new AutofillMsg_SetNodeText(
@@ -179,6 +213,10 @@ bool AutofillExternalDelegate::DidAcceptAutofillSuggestions(
}
void AutofillExternalDelegate::ClearPreviewedForm() {
+ if (password_autofill_manager_.DidClearAutofillSelection(
+ autofill_query_field_))
+ return;
+
RenderViewHost* host =
tab_contents_wrapper_->web_contents()->GetRenderViewHost();
host->Send(new AutofillMsg_ClearPreviewedForm(host->GetRoutingID()));
@@ -191,6 +229,18 @@ void AutofillExternalDelegate::HideAutofillPopup() {
HideAutofillPopupInternal();
}
+void AutofillExternalDelegate::Reset() {
+ HideAutofillPopup();
+
+ password_autofill_manager_.Reset();
+}
+
+void AutofillExternalDelegate::AddPasswordFormMapping(
+ const webkit::forms::FormField& form,
+ const webkit::forms::PasswordFormFillData& fill_data) {
+ password_autofill_manager_.AddPasswordFormMapping(form, fill_data);
+}
+
void AutofillExternalDelegate::FillAutofillFormData(int unique_id,
bool is_preview) {
RenderViewHost* host =
diff --git a/chrome/browser/autofill/autofill_external_delegate.h b/chrome/browser/autofill/autofill_external_delegate.h
index 11a5341..18aa57c 100644
--- a/chrome/browser/autofill/autofill_external_delegate.h
+++ b/chrome/browser/autofill/autofill_external_delegate.h
@@ -10,8 +10,10 @@
#include "base/compiler_specific.h"
#include "base/string16.h"
+#include "chrome/browser/autofill/password_autofill_manager.h"
#include "webkit/forms/form_data.h"
#include "webkit/forms/form_field.h"
+#include "webkit/forms/password_form_dom_manager.h"
class AutofillManager;
class TabContentsWrapper;
@@ -57,6 +59,11 @@ class AutofillExternalDelegate {
const std::vector<string16>& autofill_icons,
const std::vector<int>& autofill_unique_ids);
+ // Show password suggestions in the popup.
+ void OnShowPasswordSuggestions(const std::vector<string16>& suggestions,
+ const webkit::forms::FormField& field,
+ const gfx::Rect& bounds);
+
// Inform the delegate that the text field editing has ended, this is
// used to help record the metrics of when a new popup is shown.
void DidEndTextFieldEditing();
@@ -73,6 +80,15 @@ class AutofillExternalDelegate {
// Hide the Autofill poup.
virtual void HideAutofillPopup();
+ // Returns the delegate to its starting state by removing any page specific
+ // values or settings.
+ void Reset();
+
+ // Inform the Password Manager of a filled form.
+ void AddPasswordFormMapping(
+ const webkit::forms::FormField& form,
+ const webkit::forms::PasswordFormFillData& fill_data);
+
// Platforms that wish to implement an external Autofill delegate
// MUST implement this. The 1st arg is the tab contents that owns
// this delegate; the second is the Autofill manager owned by the
@@ -102,6 +118,9 @@ class AutofillExternalDelegate {
// Handle platform-dependent hiding.
virtual void HideAutofillPopupInternal() = 0;
+ // Set the bounds of the Autofill element being worked with.
+ virtual void SetBounds(const gfx::Rect& bounds) = 0;
+
private:
// Fills the form with the Autofill data corresponding to |unique_id|.
// If |is_preview| is true then this is just a preview to show the user what
@@ -112,6 +131,9 @@ class AutofillExternalDelegate {
TabContentsWrapper* tab_contents_wrapper_; // weak; owns me.
AutofillManager* autofill_manager_; // weak.
+ // Password Autofill manager, handles all password-related Autofilling.
+ PasswordAutofillManager password_autofill_manager_;
+
// The ID of the last request sent for form field Autofill. Used to ignore
// out of date responses.
int autofill_query_id_;
diff --git a/chrome/browser/autofill/autofill_external_delegate_gtk.cc b/chrome/browser/autofill/autofill_external_delegate_gtk.cc
index 4c7bbfa..e140d3b 100644
--- a/chrome/browser/autofill/autofill_external_delegate_gtk.cc
+++ b/chrome/browser/autofill/autofill_external_delegate_gtk.cc
@@ -61,6 +61,11 @@ void AutofillExternalDelegateGtk::ApplyAutofillSuggestions(
separator_index);
}
+void AutofillExternalDelegateGtk::SetBounds(const gfx::Rect& bounds) {
+ CreateViewIfNeeded();
+ view_->set_element_bounds(bounds);
+}
+
void AutofillExternalDelegateGtk::CreateViewIfNeeded() {
if (view_.get())
return;
diff --git a/chrome/browser/autofill/autofill_external_delegate_gtk.h b/chrome/browser/autofill/autofill_external_delegate_gtk.h
index c2f9185..aada4f0 100644
--- a/chrome/browser/autofill/autofill_external_delegate_gtk.h
+++ b/chrome/browser/autofill/autofill_external_delegate_gtk.h
@@ -40,6 +40,7 @@ class AutofillExternalDelegateGtk : public AutofillExternalDelegate {
const std::vector<string16>& autofill_icons,
const std::vector<int>& autofill_unique_ids,
int separator_index) OVERRIDE;
+ virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
private:
// Create a valid view to display the autofill results if one doesn't
diff --git a/chrome/browser/autofill/autofill_manager.cc b/chrome/browser/autofill/autofill_manager.cc
index a85cd88..902cb5f 100644
--- a/chrome/browser/autofill/autofill_manager.cc
+++ b/chrome/browser/autofill/autofill_manager.cc
@@ -60,6 +60,7 @@
#include "webkit/forms/form_data.h"
#include "webkit/forms/form_data_predictions.h"
#include "webkit/forms/form_field.h"
+#include "webkit/forms/password_form_dom_manager.h"
using base::TimeTicks;
using content::BrowserThread;
@@ -267,6 +268,10 @@ void AutofillManager::DidNavigateMainFrame(
Reset();
}
+bool AutofillManager::HasExternalDelegate() {
+ return external_delegate_ != NULL;
+}
+
bool AutofillManager::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(AutofillManager, message)
@@ -292,6 +297,10 @@ bool AutofillManager::OnMessageReceived(const IPC::Message& message) {
OnHideAutofillPopup)
IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowPasswordGenerationPopup,
OnShowPasswordGenerationPopup)
+ IPC_MESSAGE_HANDLER(AutofillHostMsg_AddPasswordFormMapping,
+ OnAddPasswordFormMapping)
+ IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowPasswordSuggestions,
+ OnShowPasswordSuggestions)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -679,6 +688,21 @@ void AutofillManager::OnShowPasswordGenerationPopup(const gfx::Rect& bounds) {
#endif // #if defined(OS_ANDROID)
}
+void AutofillManager::OnAddPasswordFormMapping(
+ const webkit::forms::FormField& form,
+ const webkit::forms::PasswordFormFillData& fill_data) {
+ if (external_delegate_)
+ external_delegate_->AddPasswordFormMapping(form, fill_data);
+}
+
+void AutofillManager::OnShowPasswordSuggestions(
+ const webkit::forms::FormField& field,
+ const gfx::Rect& bounds,
+ const std::vector<string16>& suggestions) {
+ if (external_delegate_)
+ external_delegate_->OnShowPasswordSuggestions(suggestions, field, bounds);
+}
+
void AutofillManager::OnLoadedServerPredictions(
const std::string& response_xml) {
// Parse and store the server predictions.
@@ -787,6 +811,9 @@ void AutofillManager::Reset() {
user_did_edit_autofilled_field_ = false;
forms_loaded_timestamp_ = TimeTicks();
initial_interaction_timestamp_ = TimeTicks();
+
+ if (external_delegate_)
+ external_delegate_->Reset();
}
AutofillManager::AutofillManager(TabContentsWrapper* tab_contents,
diff --git a/chrome/browser/autofill/autofill_manager.h b/chrome/browser/autofill/autofill_manager.h
index 86203c5..11bfbc0 100644
--- a/chrome/browser/autofill/autofill_manager.h
+++ b/chrome/browser/autofill/autofill_manager.h
@@ -54,6 +54,7 @@ namespace webkit {
namespace forms {
struct FormData;
struct FormField;
+struct PasswordFormFillData;
}
}
@@ -77,6 +78,9 @@ class AutofillManager : public content::WebContentsObserver,
external_delegate_ = delegate;
}
+ // Used to say if this class has an external delegate that it is using.
+ bool HasExternalDelegate();
+
// Called from our external delegate so they cannot be private.
virtual void OnFillAutofillFormData(int query_id,
const webkit::forms::FormData& form,
@@ -187,6 +191,12 @@ class AutofillManager : public content::WebContentsObserver,
bool display_warning);
void OnDidEndTextFieldEditing();
void OnHideAutofillPopup();
+ void OnAddPasswordFormMapping(
+ const webkit::forms::FormField& form,
+ const webkit::forms::PasswordFormFillData& fill_data);
+ void OnShowPasswordSuggestions(const webkit::forms::FormField& field,
+ const gfx::Rect& bounds,
+ const std::vector<string16>& suggestions);
// Fills |host| with the RenderViewHost for this tab.
// Returns false if Autofill is disabled or if the host is unavailable.
diff --git a/chrome/browser/autofill/password_autofill_manager.cc b/chrome/browser/autofill/password_autofill_manager.cc
new file mode 100644
index 0000000..6d22a7f
--- /dev/null
+++ b/chrome/browser/autofill/password_autofill_manager.cc
@@ -0,0 +1,97 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/autofill/password_autofill_manager.h"
+#include "chrome/common/autofill_messages.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// PasswordAutofillManager, public:
+
+PasswordAutofillManager::PasswordAutofillManager(
+ content::WebContents* web_contents) : web_contents_(web_contents) {
+}
+
+PasswordAutofillManager::~PasswordAutofillManager() {
+}
+
+bool PasswordAutofillManager::DidAcceptAutofillSuggestion(
+ const webkit::forms::FormField& field,
+ const string16& value) {
+ webkit::forms::PasswordFormFillData password;
+ if (!FindLoginInfo(field, &password))
+ return false;
+
+ if (WillFillUserNameAndPassword(value, password)) {
+ if (web_contents_) {
+ content::RenderViewHost* render_view_host =
+ web_contents_->GetRenderViewHost();
+ render_view_host->Send(new AutofillMsg_AcceptPasswordAutofillSuggestion(
+ render_view_host->GetRoutingID(),
+ value));
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool PasswordAutofillManager::DidSelectAutofillSuggestion(
+ const webkit::forms::FormField& field) {
+ webkit::forms::FormField input;
+ webkit::forms::PasswordFormFillData password;
+ return FindLoginInfo(field, &password);
+}
+
+bool PasswordAutofillManager::DidClearAutofillSelection(
+ const webkit::forms::FormField& field) {
+ webkit::forms::FormField input;
+ webkit::forms::PasswordFormFillData password;
+ return FindLoginInfo(field, &password);
+}
+
+void PasswordAutofillManager::AddPasswordFormMapping(
+ const webkit::forms::FormField& username_element,
+ const webkit::forms::PasswordFormFillData& password) {
+ login_to_password_info_[username_element] = password;
+}
+
+void PasswordAutofillManager::Reset() {
+ login_to_password_info_.clear();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// PasswordAutofillManager, private:
+
+bool PasswordAutofillManager::WillFillUserNameAndPassword(
+ const string16& current_username,
+ const webkit::forms::PasswordFormFillData& fill_data) {
+ // Look for any suitable matches to current field text.
+ if (fill_data.basic_data.fields[0].value == current_username) {
+ return true;
+ } else {
+ // Scan additional logins for a match.
+ webkit::forms::PasswordFormFillData::LoginCollection::const_iterator iter;
+ for (iter = fill_data.additional_logins.begin();
+ iter != fill_data.additional_logins.end(); ++iter) {
+ if (iter->first == current_username)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool PasswordAutofillManager::FindLoginInfo(
+ const webkit::forms::FormField& field,
+ webkit::forms::PasswordFormFillData* found_password) {
+ LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(field);
+ if (iter == login_to_password_info_.end())
+ return false;
+
+ *found_password = iter->second;
+ return true;
+}
diff --git a/chrome/browser/autofill/password_autofill_manager.h b/chrome/browser/autofill/password_autofill_manager.h
new file mode 100644
index 0000000..46d4b8e
--- /dev/null
+++ b/chrome/browser/autofill/password_autofill_manager.h
@@ -0,0 +1,81 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_AUTOFILL_PASSWORD_AUTOFILL_MANAGER_H_
+#define CHROME_BROWSER_AUTOFILL_PASSWORD_AUTOFILL_MANAGER_H_
+#pragma once
+
+// This file was contains some repeated code from
+// chrome/renderer/autofill/password_autofill_manager because as we move to the
+// new Autofill UI we needs these functions in both the browser and renderer.
+// Once the move is completed the repeated code in the renderer half should be
+// removed.
+// http://crbug.com/51644
+
+#include <map>
+
+#include "webkit/forms/password_form_dom_manager.h"
+
+namespace content {
+class WebContents;
+} // namespace content
+
+// This class is responsible for filling password forms.
+class PasswordAutofillManager {
+ public:
+ explicit PasswordAutofillManager(content::WebContents* web_contents);
+ virtual ~PasswordAutofillManager();
+
+ // Fills the password associated with user name |value|. Returns true if the
+ // username and password fields were filled, false otherwise.
+ bool DidAcceptAutofillSuggestion(const webkit::forms::FormField& field,
+ const string16& value);
+
+ // A no-op. No filling happens for selection. But this method returns
+ // true when |node| is fillable by password Autofill.
+ bool DidSelectAutofillSuggestion(const webkit::forms::FormField& field);
+
+ // A no-op. Password forms are not previewed, so they do not need to be
+ // cleared when the selection changes. However, this method returns
+ // true when |node| is fillable by password Autofill.
+ bool DidClearAutofillSelection(const webkit::forms::FormField& field);
+
+ // Invoked when a password mapping is added.
+ void AddPasswordFormMapping(
+ const webkit::forms::FormField& username_element,
+ const webkit::forms::PasswordFormFillData& password);
+
+ // Invoked to clear any page specific cached values.
+ void Reset();
+
+ private:
+ // TODO(csharp): Modify the AutofillExternalDeletegate code so that it can
+ // figure out if a entry is a password one without using this mapping.
+ // crbug.com/118601
+ typedef std::map<webkit::forms::FormField,
+ webkit::forms::PasswordFormFillData>
+ LoginToPasswordInfoMap;
+
+ // Returns true if |current_username| matches a username for one of the
+ // login mappings in |password|.
+ bool WillFillUserNameAndPassword(
+ const string16& current_username,
+ const webkit::forms::PasswordFormFillData& password);
+
+ // Finds login information for a |node| that was previously filled.
+ bool FindLoginInfo(const webkit::forms::FormField& field,
+ webkit::forms::PasswordFormFillData* found_password);
+
+ // The logins we have filled so far with their associated info.
+ LoginToPasswordInfoMap login_to_password_info_;
+
+ // We only need the RenderViewHost pointer in WebContents, but if we attempt
+ // to just store RenderViewHost on creation, it becomes invalid once we start
+ // using it. By having the WebContents we can always get a valid pointer.
+ content::WebContents* web_contents_; // Weak reference.
+
+ DISALLOW_COPY_AND_ASSIGN(PasswordAutofillManager);
+};
+
+#endif // CHROME_BROWSER_AUTOFILL_PASSWORD_AUTOFILL_MANAGER_H_
diff --git a/chrome/browser/autofill/password_autofill_manager_unittest.cc b/chrome/browser/autofill/password_autofill_manager_unittest.cc
new file mode 100644
index 0000000..325f31e
--- /dev/null
+++ b/chrome/browser/autofill/password_autofill_manager_unittest.cc
@@ -0,0 +1,94 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/compiler_specific.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/autofill/password_autofill_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+// The name of the username/password element in the form.
+const char* const kUsernameName = "username";
+const char* const kInvalidUsername = "no-username";
+const char* const kPasswordName = "password";
+
+const char* const kAliceUsername = "alice";
+const char* const kAlicePassword = "password";
+
+const char* const kValue = "password";
+
+} // namespace
+
+class PasswordAutofillManagerTest : public testing::Test {
+ protected:
+ PasswordAutofillManagerTest() : password_autofill_manager_(NULL) {}
+
+ virtual void SetUp() OVERRIDE {
+ // Add a preferred login and an additional login to the FillData.
+ string16 username1 = ASCIIToUTF16(kAliceUsername);
+ string16 password1 = ASCIIToUTF16(kAlicePassword);
+
+ username_field_.name = ASCIIToUTF16(kUsernameName);
+ username_field_.value = username1;
+ fill_data_.basic_data.fields.push_back(username_field_);
+
+ webkit::forms::FormField password_field;
+ password_field.name = ASCIIToUTF16(kPasswordName);
+ password_field.value = password1;
+ fill_data_.basic_data.fields.push_back(password_field);
+
+ password_autofill_manager_.AddPasswordFormMapping(username_field_,
+ fill_data_);
+ }
+
+ PasswordAutofillManager* password_autofill_manager() {
+ return &password_autofill_manager_;
+ }
+
+ const webkit::forms::FormField& username_field() { return username_field_; }
+
+ private:
+ webkit::forms::PasswordFormFillData fill_data_;
+ webkit::forms::FormField username_field_;
+
+ PasswordAutofillManager password_autofill_manager_;
+};
+
+TEST_F(PasswordAutofillManagerTest, DidAcceptAutofillSuggestion) {
+ EXPECT_TRUE(password_autofill_manager()->DidAcceptAutofillSuggestion(
+ username_field(), ASCIIToUTF16(kAliceUsername)));
+ EXPECT_FALSE(password_autofill_manager()->DidAcceptAutofillSuggestion(
+ username_field(), ASCIIToUTF16(kInvalidUsername)));
+
+ webkit::forms::FormField invalid_username_field;
+ invalid_username_field.name = ASCIIToUTF16(kInvalidUsername);
+
+ EXPECT_FALSE(password_autofill_manager()->DidAcceptAutofillSuggestion(
+ invalid_username_field, ASCIIToUTF16(kAliceUsername)));
+
+ password_autofill_manager()->Reset();
+ EXPECT_FALSE(password_autofill_manager()->DidAcceptAutofillSuggestion(
+ username_field(), ASCIIToUTF16(kAliceUsername)));
+}
+
+TEST_F(PasswordAutofillManagerTest, DidSelectAutofillSuggestion) {
+ EXPECT_TRUE(password_autofill_manager()->DidSelectAutofillSuggestion(
+ username_field()));
+
+ password_autofill_manager()->Reset();
+
+ EXPECT_FALSE(password_autofill_manager()->DidSelectAutofillSuggestion(
+ username_field()));
+}
+
+TEST_F(PasswordAutofillManagerTest, DidClearAutofillSelection) {
+ EXPECT_TRUE(password_autofill_manager()->DidClearAutofillSelection(
+ username_field()));
+
+ password_autofill_manager()->Reset();
+
+ EXPECT_FALSE(password_autofill_manager()->DidClearAutofillSelection(
+ username_field()));
+}
diff --git a/chrome/browser/autofill/test_autofill_external_delegate.cc b/chrome/browser/autofill/test_autofill_external_delegate.cc
index 9f076f1..c461bb4 100644
--- a/chrome/browser/autofill/test_autofill_external_delegate.cc
+++ b/chrome/browser/autofill/test_autofill_external_delegate.cc
@@ -24,3 +24,5 @@ void TestAutofillExternalDelegate::OnQueryPlatformSpecific(
const gfx::Rect& bounds) {}
void TestAutofillExternalDelegate::HideAutofillPopupInternal() {}
+
+void TestAutofillExternalDelegate::SetBounds(const gfx::Rect& bounds) {}
diff --git a/chrome/browser/autofill/test_autofill_external_delegate.h b/chrome/browser/autofill/test_autofill_external_delegate.h
index 771fcf8..6b95d85 100644
--- a/chrome/browser/autofill/test_autofill_external_delegate.h
+++ b/chrome/browser/autofill/test_autofill_external_delegate.h
@@ -35,6 +35,8 @@ class TestAutofillExternalDelegate : public AutofillExternalDelegate {
virtual void HideAutofillPopupInternal() OVERRIDE;
+ virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
+
private:
DISALLOW_COPY_AND_ASSIGN(TestAutofillExternalDelegate);
};
diff --git a/chrome/browser/password_manager_delegate_impl.cc b/chrome/browser/password_manager_delegate_impl.cc
index 5a3b572..f0caecb 100644
--- a/chrome/browser/password_manager_delegate_impl.cc
+++ b/chrome/browser/password_manager_delegate_impl.cc
@@ -6,6 +6,7 @@
#include "base/memory/singleton.h"
#include "base/metrics/histogram.h"
+#include "chrome/browser/autofill/autofill_manager.h"
#include "chrome/browser/infobars/infobar_tab_helper.h"
#include "chrome/browser/password_manager/password_form_manager.h"
#include "chrome/browser/password_manager/password_manager.h"
@@ -123,10 +124,13 @@ SavePasswordInfoBarDelegate::AsSavePasswordInfoBarDelegate() {
void PasswordManagerDelegateImpl::FillPasswordForm(
const webkit::forms::PasswordFormFillData& form_data) {
+ bool disable_popup = tab_contents_->autofill_manager()->HasExternalDelegate();
+
tab_contents_->web_contents()->GetRenderViewHost()->Send(
new AutofillMsg_FillPasswordForm(
tab_contents_->web_contents()->GetRenderViewHost()->GetRoutingID(),
- form_data));
+ form_data,
+ disable_popup));
}
void PasswordManagerDelegateImpl::AddSavePasswordInfoBarIfPermitted(