diff options
author | tedchoc@chromium.org <tedchoc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-11 19:43:24 +0000 |
---|---|---|
committer | tedchoc@chromium.org <tedchoc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-11 19:43:24 +0000 |
commit | 3a13eeb48780dc76e7be6aa8e90b26c201103247 (patch) | |
tree | 36e68100fd2197ed2024535a6954d16e03106051 /chrome/browser/password_manager | |
parent | 300187dbb471bbca8002a5733f7c74a2316ec60a (diff) | |
download | chromium_src-3a13eeb48780dc76e7be6aa8e90b26c201103247.zip chromium_src-3a13eeb48780dc76e7be6aa8e90b26c201103247.tar.gz chromium_src-3a13eeb48780dc76e7be6aa8e90b26c201103247.tar.bz2 |
Add support for embedders to require authentication before autofilling passwords.
Currently, this feature is only supported on Android devices, but this provides
the basic hooks to allow requiring additional auth before providing autofilled
passwords.
BUG=341492
Review URL: https://codereview.chromium.org/159203004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@250473 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/password_manager')
6 files changed, 79 insertions, 4 deletions
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc index a710569..a3d8926 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.cc +++ b/chrome/browser/password_manager/chrome_password_manager_client.cc @@ -4,6 +4,7 @@ #include "chrome/browser/password_manager/chrome_password_manager_client.h" +#include "base/bind_helpers.h" #include "base/command_line.h" #include "base/memory/singleton.h" #include "base/metrics/histogram.h" @@ -20,6 +21,10 @@ #include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "content/public/browser/web_contents.h" +#if defined(OS_ANDROID) +#include "chrome/browser/android/password_authentication_manager.h" +#endif // OS_ANDROID + namespace { void ReportOsPassword() { @@ -37,7 +42,9 @@ DEFINE_WEB_CONTENTS_USER_DATA_KEY(ChromePasswordManagerClient); ChromePasswordManagerClient::ChromePasswordManagerClient( content::WebContents* web_contents) - : web_contents_(web_contents), driver_(web_contents, this) { + : web_contents_(web_contents), + driver_(web_contents, this), + weak_factory_(this) { // Avoid checking OS password until later on in browser startup // since it calls a few Windows APIs. base::MessageLoopProxy::current()->PostDelayedTask( @@ -80,6 +87,25 @@ void ChromePasswordManagerClient::PasswordWasAutofilled( } } +void ChromePasswordManagerClient::AuthenticateAutofillAndFillForm( + scoped_ptr<autofill::PasswordFormFillData> fill_data) { +#if defined(OS_ANDROID) + if (PasswordAuthenticationManager + ::IsAutofillPasswordAuthenticationEnabled()) { + PasswordAuthenticationManager::AuthenticatePasswordAutofill( + web_contents_, + base::Bind(&ChromePasswordManagerClient::CommitFillPasswordForm, + weak_factory_.GetWeakPtr(), + base::Owned(fill_data.release()))); + return; + } +#endif // OS_ANDROID + + // Additional authentication is currently only available for Android, so all + // other plaftorms should just fill the password form directly. + CommitFillPasswordForm(fill_data.get()); +} + Profile* ChromePasswordManagerClient::GetProfile() { return Profile::FromBrowserContext(web_contents_->GetBrowserContext()); } @@ -137,3 +163,8 @@ PasswordManager* ChromePasswordManagerClient::GetManagerFromWebContents( return NULL; return client->GetDriver()->GetPasswordManager(); } + +void ChromePasswordManagerClient::CommitFillPasswordForm( + autofill::PasswordFormFillData* data) { + driver_.FillPasswordForm(*data); +} diff --git a/chrome/browser/password_manager/chrome_password_manager_client.h b/chrome/browser/password_manager/chrome_password_manager_client.h index 076d892..2511037 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.h +++ b/chrome/browser/password_manager/chrome_password_manager_client.h @@ -30,6 +30,8 @@ class ChromePasswordManagerClient OVERRIDE; virtual void PasswordWasAutofilled( const autofill::PasswordFormMap& best_matches) const OVERRIDE; + virtual void AuthenticateAutofillAndFillForm( + scoped_ptr<autofill::PasswordFormFillData> fill_data) OVERRIDE; virtual Profile* GetProfile() OVERRIDE; virtual PrefService* GetPrefs() OVERRIDE; virtual PasswordManagerDriver* GetDriver() OVERRIDE; @@ -52,9 +54,17 @@ class ChromePasswordManagerClient explicit ChromePasswordManagerClient(content::WebContents* web_contents); friend class content::WebContentsUserData<ChromePasswordManagerClient>; + // Callback method to be triggered when authentication is successful for a + // given password authentication request. If authentication is disabled or + // not supported, this will be triggered directly. + void CommitFillPasswordForm(autofill::PasswordFormFillData* fill_data); + content::WebContents* web_contents_; ContentPasswordManagerDriver driver_; + // Allows authentication callbacks to be destroyed when this client is gone. + base::WeakPtrFactory<ChromePasswordManagerClient> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(ChromePasswordManagerClient); }; diff --git a/chrome/browser/password_manager/password_form_manager_unittest.cc b/chrome/browser/password_manager/password_form_manager_unittest.cc index 11af0ba..2db3577 100644 --- a/chrome/browser/password_manager/password_form_manager_unittest.cc +++ b/chrome/browser/password_manager/password_form_manager_unittest.cc @@ -59,6 +59,10 @@ class TestPasswordManagerClient : public PasswordManagerClient { virtual Profile* GetProfile() OVERRIDE { return profile_; } virtual PrefService* GetPrefs() OVERRIDE { return profile_->GetPrefs(); } virtual PasswordManagerDriver* GetDriver() OVERRIDE { return &driver_; } + virtual void AuthenticateAutofillAndFillForm( + scoped_ptr<autofill::PasswordFormFillData> fill_data) OVERRIDE { + driver_.FillPasswordForm(*fill_data.get()); + } MockPasswordManagerDriver* GetMockDriver() { return &driver_; } diff --git a/chrome/browser/password_manager/password_manager.cc b/chrome/browser/password_manager/password_manager.cc index 96d9965..28057d4 100644 --- a/chrome/browser/password_manager/password_manager.cc +++ b/chrome/browser/password_manager/password_manager.cc @@ -354,18 +354,33 @@ void PasswordManager::Autofill( const PasswordForm& preferred_match, bool wait_for_username) const { PossiblyInitializeUsernamesExperiment(best_matches); + + // TODO(tedchoc): Switch to only requesting authentication if the user is + // acting on the autofilled forms (crbug.com/342594) instead + // of on page load. + bool authentication_required = preferred_match.use_additional_authentication; + for (autofill::PasswordFormMap::const_iterator it = best_matches.begin(); + !authentication_required && it != best_matches.end(); ++it) { + if (it->second->use_additional_authentication) + authentication_required = true; + } + switch (form_for_autofill.scheme) { case PasswordForm::SCHEME_HTML: { // Note the check above is required because the observers_ for a non-HTML // schemed password form may have been freed, so we need to distinguish. - autofill::PasswordFormFillData fill_data; + scoped_ptr<autofill::PasswordFormFillData> fill_data( + new autofill::PasswordFormFillData()); InitPasswordFormFillData(form_for_autofill, best_matches, &preferred_match, wait_for_username, OtherPossibleUsernamesEnabled(), - &fill_data); - driver_->FillPasswordForm(fill_data); + fill_data.get()); + if (authentication_required) + client_->AuthenticateAutofillAndFillForm(fill_data.Pass()); + else + driver_->FillPasswordForm(*fill_data.get()); break; } default: diff --git a/chrome/browser/password_manager/password_manager_client.h b/chrome/browser/password_manager/password_manager_client.h index 19c621c..e45fd8d 100644 --- a/chrome/browser/password_manager/password_manager_client.h +++ b/chrome/browser/password_manager/password_manager_client.h @@ -7,6 +7,7 @@ #include "base/metrics/field_trial.h" #include "components/autofill/core/common/password_form.h" +#include "components/autofill/core/common/password_form_fill_data.h" class PasswordFormManager; class PasswordManagerDriver; @@ -30,6 +31,11 @@ class PasswordManagerClient { virtual void PasswordWasAutofilled( const autofill::PasswordFormMap& best_matches) const {} + // Called to authenticate the autofill password data. If authentication is + // successful, this should continue filling the form. + virtual void AuthenticateAutofillAndFillForm( + scoped_ptr<autofill::PasswordFormFillData> fill_data) = 0; + // Get the profile for which we are managing passwords. // TODO(gcasto): Remove this function. crbug.com/335107. virtual Profile* GetProfile() = 0; diff --git a/chrome/browser/password_manager/password_manager_unittest.cc b/chrome/browser/password_manager/password_manager_unittest.cc index ad23a7b..92a945f 100644 --- a/chrome/browser/password_manager/password_manager_unittest.cc +++ b/chrome/browser/password_manager/password_manager_unittest.cc @@ -46,6 +46,15 @@ class MockPasswordManagerClient : public PasswordManagerClient { MOCK_METHOD0(GetDriver, PasswordManagerDriver*()); MOCK_METHOD1(GetProbabilityForExperiment, base::FieldTrial::Probability(const std::string&)); + + // The following is required because GMock does not support move-only + // parameters. + MOCK_METHOD1(AuthenticateAutofillAndFillFormPtr, + void(autofill::PasswordFormFillData* fill_data)); + virtual void AuthenticateAutofillAndFillForm( + scoped_ptr<autofill::PasswordFormFillData> fill_data) OVERRIDE { + return AuthenticateAutofillAndFillFormPtr(fill_data.release()); + } }; class MockPasswordManagerDriver : public PasswordManagerDriver { |