diff options
author | gcasto@chromium.org <gcasto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-31 03:37:03 +0000 |
---|---|---|
committer | gcasto@chromium.org <gcasto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-31 03:37:03 +0000 |
commit | cfe7bed7b0fe35db7cd8d6d95874df02e00c933e (patch) | |
tree | 9b393d6be68b56718fd8eab76980d5a989f0d069 /components | |
parent | 5c0e8bc57db197847190040ab7219471125d1bbc (diff) | |
download | chromium_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')
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_; |