summaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorgcasto@chromium.org <gcasto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-31 03:37:03 +0000
committergcasto@chromium.org <gcasto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-31 03:37:03 +0000
commitcfe7bed7b0fe35db7cd8d6d95874df02e00c933e (patch)
tree9b393d6be68b56718fd8eab76980d5a989f0d069 /components
parent5c0e8bc57db197847190040ab7219471125d1bbc (diff)
downloadchromium_src-cfe7bed7b0fe35db7cd8d6d95874df02e00c933e.zip
chromium_src-cfe7bed7b0fe35db7cd8d6d95874df02e00c933e.tar.gz
chromium_src-cfe7bed7b0fe35db7cd8d6d95874df02e00c933e.tar.bz2
Enable UI for possible username selection via Finch experiment.
This feature will only be enabled on Dev/Beta until we collect stats proving it's worth. BUG=188908 Review URL: https://chromiumcodereview.appspot.com/13843015 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@203319 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components')
-rw-r--r--components/autofill/browser/password_autofill_manager.cc23
-rw-r--r--components/autofill/common/autofill_messages.h6
-rw-r--r--components/autofill/common/password_form_fill_data.cc24
-rw-r--r--components/autofill/common/password_form_fill_data.h26
-rw-r--r--components/autofill/renderer/password_autofill_agent.cc50
-rw-r--r--components/autofill/renderer/password_autofill_agent.h13
6 files changed, 131 insertions, 11 deletions
diff --git a/components/autofill/browser/password_autofill_manager.cc b/components/autofill/browser/password_autofill_manager.cc
index bdd0971..55ae9a1 100644
--- a/components/autofill/browser/password_autofill_manager.cc
+++ b/components/autofill/browser/password_autofill_manager.cc
@@ -58,14 +58,23 @@ bool PasswordAutofillManager::WillFillUserNameAndPassword(
const base::string16& current_username,
const PasswordFormFillData& fill_data) {
// Look for any suitable matches to current field text.
- if (fill_data.basic_data.fields[0].value == current_username) {
+ if (fill_data.basic_data.fields[0].value == current_username)
return true;
- } else {
- // Scan additional logins for a match.
- PasswordFormFillData::LoginCollection::const_iterator iter;
- for (iter = fill_data.additional_logins.begin();
- iter != fill_data.additional_logins.end(); ++iter) {
- if (iter->first == current_username)
+
+ // Scan additional logins for a match.
+ for (PasswordFormFillData::LoginCollection::const_iterator iter =
+ fill_data.additional_logins.begin();
+ iter != fill_data.additional_logins.end(); ++iter) {
+ if (iter->first == current_username)
+ return true;
+ }
+
+ for (PasswordFormFillData::UsernamesCollection::const_iterator usernames_iter
+ = fill_data.other_possible_usernames.begin();
+ usernames_iter != fill_data.other_possible_usernames.end();
+ ++usernames_iter) {
+ for (size_t i = 0; i < usernames_iter->second.size(); ++i) {
+ if (usernames_iter->second[i] == current_username)
return true;
}
}
diff --git a/components/autofill/common/autofill_messages.h b/components/autofill/common/autofill_messages.h
index f8efa89..35b6b69 100644
--- a/components/autofill/common/autofill_messages.h
+++ b/components/autofill/common/autofill_messages.h
@@ -77,9 +77,15 @@ IPC_STRUCT_TRAITS_BEGIN(autofill::FormDataPredictions)
IPC_STRUCT_TRAITS_MEMBER(fields)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(autofill::UsernamesCollectionKey)
+ IPC_STRUCT_TRAITS_MEMBER(username)
+ IPC_STRUCT_TRAITS_MEMBER(password)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(autofill::PasswordFormFillData)
IPC_STRUCT_TRAITS_MEMBER(basic_data)
IPC_STRUCT_TRAITS_MEMBER(additional_logins)
+ IPC_STRUCT_TRAITS_MEMBER(other_possible_usernames)
IPC_STRUCT_TRAITS_MEMBER(wait_for_username)
IPC_STRUCT_TRAITS_END()
diff --git a/components/autofill/common/password_form_fill_data.cc b/components/autofill/common/password_form_fill_data.cc
index 535725c..e31823d 100644
--- a/components/autofill/common/password_form_fill_data.cc
+++ b/components/autofill/common/password_form_fill_data.cc
@@ -9,6 +9,17 @@
namespace autofill {
+UsernamesCollectionKey::UsernamesCollectionKey() {}
+
+UsernamesCollectionKey::~UsernamesCollectionKey() {}
+
+bool UsernamesCollectionKey::operator<(
+ const UsernamesCollectionKey& other) const {
+ if (username != other.username)
+ return username < other.username;
+ return password < other.password;
+}
+
PasswordFormFillData::PasswordFormFillData() : wait_for_username(false) {
}
@@ -20,6 +31,7 @@ void InitPasswordFormFillData(
const content::PasswordFormMap& matches,
const content::PasswordForm* const preferred_match,
bool wait_for_username_before_autofill,
+ bool enable_other_possible_usernames,
PasswordFormFillData* result) {
// Note that many of the |FormFieldData| members are not initialized for
// |username_field| and |password_field| because they are currently not used
@@ -43,6 +55,18 @@ void InitPasswordFormFillData(
for (iter = matches.begin(); iter != matches.end(); iter++) {
if (iter->second != preferred_match)
result->additional_logins[iter->first] = iter->second->password_value;
+ if (enable_other_possible_usernames &&
+ !iter->second->other_possible_usernames.empty()) {
+ // Note that there may be overlap between other_possible_usernames and
+ // other saved usernames or with other other_possible_usernames. For now
+ // we will ignore this overlap as it should be a rare occurence. We may
+ // want to revisit this in the future.
+ UsernamesCollectionKey key;
+ key.username = iter->first;
+ key.password = iter->second->password_value;
+ result->other_possible_usernames[key] =
+ iter->second->other_possible_usernames;
+ }
}
}
diff --git a/components/autofill/common/password_form_fill_data.h b/components/autofill/common/password_form_fill_data.h
index b0de41b..1c6091a 100644
--- a/components/autofill/common/password_form_fill_data.h
+++ b/components/autofill/common/password_form_fill_data.h
@@ -13,10 +13,26 @@
namespace autofill {
+// Helper struct for PasswordFormFillData
+struct UsernamesCollectionKey {
+ UsernamesCollectionKey();
+ ~UsernamesCollectionKey();
+
+ // Defined so that this struct can be used as a key in a std::map.
+ bool operator<(const UsernamesCollectionKey& other) const;
+
+ base::string16 username;
+ base::string16 password;
+};
+
// Structure used for autofilling password forms.
// basic_data identifies the HTML form on the page and preferred username/
// password for login, while
// additional_logins is a list of other matching user/pass pairs for the form.
+// other_possible_usernames is a list of possible usernames in the case where we
+// aren't completely sure that the original saved username is correct.
+// This data is keyed by the saved username/password to ensure uniqueness,
+// though the username is not used.
// wait_for_username tells us whether we need to wait for the user to enter
// a valid username before we autofill the password. By default, this is off
// unless the PasswordManager determined there is an additional risk
@@ -24,9 +40,12 @@ namespace autofill {
// of the observed form and our saved representation don't match up.
struct PasswordFormFillData {
typedef std::map<base::string16, base::string16> LoginCollection;
+ typedef std::map<UsernamesCollectionKey,
+ std::vector<base::string16> > UsernamesCollection;
FormData basic_data;
LoginCollection additional_logins;
+ UsernamesCollection other_possible_usernames;
bool wait_for_username;
PasswordFormFillData();
~PasswordFormFillData();
@@ -35,14 +54,17 @@ struct PasswordFormFillData {
// Create a FillData structure in preparation for autofilling a form,
// from basic_data identifying which form to fill, and a collection of
// matching stored logins to use as username/password values.
-// preferred_match should equal (address) one of matches.
-// wait_for_username_before_autofill is true if we should not autofill
+// |preferred_match| should equal (address) one of matches.
+// |wait_for_username_before_autofill| is true if we should not autofill
// anything until the user typed in a valid username and blurred the field.
+// If |enable_possible_usernames| is true, we will populate possible_usernames
+// in |result|.
void InitPasswordFormFillData(
const content::PasswordForm& form_on_page,
const content::PasswordFormMap& matches,
const content::PasswordForm* const preferred_match,
bool wait_for_username_before_autofill,
+ bool enable_other_possible_usernames,
PasswordFormFillData* result);
} // namespace autofill
diff --git a/components/autofill/renderer/password_autofill_agent.cc b/components/autofill/renderer/password_autofill_agent.cc
index c185f25..7ff58b1 100644
--- a/components/autofill/renderer/password_autofill_agent.cc
+++ b/components/autofill/renderer/password_autofill_agent.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
+#include "base/metrics/histogram.h"
#include "components/autofill/common/autofill_messages.h"
#include "components/autofill/common/form_field_data.h"
#include "components/autofill/common/password_form_fill_data.h"
@@ -206,6 +207,7 @@ bool DoUsernamesMatch(const base::string16& username1,
PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view)
: content::RenderViewObserver(render_view),
disable_popup_(false),
+ usernames_usage_(NOTHING_TO_AUTOFILL),
web_view_(render_view->GetWebView()),
weak_ptr_factory_(this) {
}
@@ -392,6 +394,14 @@ bool PasswordAutofillAgent::OnMessageReceived(const IPC::Message& message) {
return handled;
}
+void PasswordAutofillAgent::DidStartLoading() {
+ if (usernames_usage_ != NOTHING_TO_AUTOFILL) {
+ UMA_HISTOGRAM_ENUMERATION("PasswordManager.OtherPossibleUsernamesUsage",
+ usernames_usage_, OTHER_POSSIBLE_USERNAMES_MAX);
+ usernames_usage_ = NOTHING_TO_AUTOFILL;
+ }
+}
+
void PasswordAutofillAgent::DidFinishDocumentLoad(WebKit::WebFrame* frame) {
// The |frame| contents have been parsed, but not yet rendered. Let the
// PasswordManager know that forms are loaded, even though we can't yet tell
@@ -419,6 +429,12 @@ void PasswordAutofillAgent::OnFillPasswordForm(
const PasswordFormFillData& form_data,
bool disable_popup) {
disable_popup_ = disable_popup;
+ if (usernames_usage_ == NOTHING_TO_AUTOFILL) {
+ if (form_data.other_possible_usernames.size())
+ usernames_usage_ = OTHER_POSSIBLE_USERNAMES_PRESENT;
+ else if (usernames_usage_ == NOTHING_TO_AUTOFILL)
+ usernames_usage_ = OTHER_POSSIBLE_USERNAMES_ABSENT;
+ }
FormElementsList forms;
// We own the FormElements* in forms.
@@ -474,12 +490,23 @@ void PasswordAutofillAgent::GetSuggestions(
if (StartsWith(fill_data.basic_data.fields[0].value, input, false))
suggestions->push_back(fill_data.basic_data.fields[0].value);
- PasswordFormFillData::LoginCollection::const_iterator iter;
- for (iter = fill_data.additional_logins.begin();
+ for (PasswordFormFillData::LoginCollection::const_iterator iter =
+ fill_data.additional_logins.begin();
iter != fill_data.additional_logins.end(); ++iter) {
if (StartsWith(iter->first, input, false))
suggestions->push_back(iter->first);
}
+
+ for (PasswordFormFillData::UsernamesCollection::const_iterator iter =
+ fill_data.other_possible_usernames.begin();
+ iter != fill_data.other_possible_usernames.end(); ++iter) {
+ for (size_t i = 0; i < iter->second.size(); ++i) {
+ if (StartsWith(iter->second[i], input, false)) {
+ usernames_usage_ = OTHER_POSSIBLE_USERNAME_SHOWN;
+ suggestions->push_back(iter->second[i]);
+ }
+ }
+ }
}
bool PasswordAutofillAgent::ShowSuggestionPopup(
@@ -560,6 +587,25 @@ bool PasswordAutofillAgent::FillUserNameAndPassword(
break;
}
}
+
+ // Check possible usernames.
+ if (username.empty() && password.empty()) {
+ for (PasswordFormFillData::UsernamesCollection::const_iterator iter =
+ fill_data.other_possible_usernames.begin();
+ iter != fill_data.other_possible_usernames.end(); ++iter) {
+ for (size_t i = 0; i < iter->second.size(); ++i) {
+ if (DoUsernamesMatch(iter->second[i], current_username,
+ exact_username_match)) {
+ usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED;
+ username = iter->second[i];
+ password = iter->first.password;
+ break;
+ }
+ }
+ if (!username.empty() && !password.empty())
+ break;
+ }
+ }
}
if (password.empty())
return false; // No match was found.
diff --git a/components/autofill/renderer/password_autofill_agent.h b/components/autofill/renderer/password_autofill_agent.h
index 1816ccb..62354f9 100644
--- a/components/autofill/renderer/password_autofill_agent.h
+++ b/components/autofill/renderer/password_autofill_agent.h
@@ -54,6 +54,15 @@ class PasswordAutofillAgent : public content::RenderViewObserver {
private:
friend class PasswordAutofillAgentTest;
+ enum OtherPossibleUsernamesUsage {
+ NOTHING_TO_AUTOFILL,
+ OTHER_POSSIBLE_USERNAMES_ABSENT,
+ OTHER_POSSIBLE_USERNAMES_PRESENT,
+ OTHER_POSSIBLE_USERNAME_SHOWN,
+ OTHER_POSSIBLE_USERNAME_SELECTED,
+ OTHER_POSSIBLE_USERNAMES_MAX
+ };
+
struct PasswordInfo {
WebKit::WebInputElement password_field;
PasswordFormFillData fill_data;
@@ -64,6 +73,7 @@ class PasswordAutofillAgent : public content::RenderViewObserver {
// RenderViewObserver:
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ virtual void DidStartLoading() OVERRIDE;
virtual void DidFinishDocumentLoad(WebKit::WebFrame* frame) OVERRIDE;
virtual void DidFinishLoad(WebKit::WebFrame* frame) OVERRIDE;
virtual void FrameDetached(WebKit::WebFrame* frame) OVERRIDE;
@@ -113,6 +123,9 @@ class PasswordAutofillAgent : public content::RenderViewObserver {
// Used to disable and hide the popup.
bool disable_popup_;
+ // Used for UMA stats.
+ OtherPossibleUsernamesUsage usernames_usage_;
+
// Pointer to the WebView. Used to access page scale factor.
WebKit::WebView* web_view_;