Commit f720ade6 authored by Maxim Kolosovskiy's avatar Maxim Kolosovskiy Committed by Commit Bot

[Passwords] Implement PasswordScriptsFetching flag

This CL also renames |has_script| to |has_startable_script| as the flag
is true only if the username is not empty and password sync is on.

Bug: 1132230
Change-Id: I27493c04629a61af788e20f4a6c81ddd542e590a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2436339
Commit-Queue: Maxim Kolosovskiy  <kolos@chromium.org>
Reviewed-by: default avatarIoana Pandele <ioanap@chromium.org>
Cr-Commit-Position: refs/heads/master@{#812050}
parent 058184ec
...@@ -64,7 +64,7 @@ class PasswordCheckBridge { ...@@ -64,7 +64,7 @@ class PasswordCheckBridge {
// TODO(crbug.com/1102025): Add call from native. // TODO(crbug.com/1102025): Add call from native.
void onCompromisedCredentialFound(String signonRealm, GURL origin, String username, void onCompromisedCredentialFound(String signonRealm, GURL origin, String username,
String displayOrigin, String displayUsername, String password, String passwordChangeUrl, String displayOrigin, String displayUsername, String password, String passwordChangeUrl,
String associatedApp, long creationTime, boolean hasScript, String associatedApp, long creationTime, boolean hasStartableScript,
boolean hasAutoChangeButton) { boolean hasAutoChangeButton) {
assert signonRealm != null; assert signonRealm != null;
assert displayOrigin != null; assert displayOrigin != null;
...@@ -72,7 +72,7 @@ class PasswordCheckBridge { ...@@ -72,7 +72,7 @@ class PasswordCheckBridge {
assert password != null; assert password != null;
mPasswordCheckObserver.onCompromisedCredentialFound(new CompromisedCredential(signonRealm, mPasswordCheckObserver.onCompromisedCredentialFound(new CompromisedCredential(signonRealm,
origin, username, displayOrigin, displayUsername, password, passwordChangeUrl, origin, username, displayOrigin, displayUsername, password, passwordChangeUrl,
associatedApp, creationTime, true, false, hasScript, hasAutoChangeButton)); associatedApp, creationTime, true, false, hasStartableScript, hasAutoChangeButton));
} }
@CalledByNative @CalledByNative
...@@ -99,11 +99,11 @@ class PasswordCheckBridge { ...@@ -99,11 +99,11 @@ class PasswordCheckBridge {
private static void insertCredential(CompromisedCredential[] credentials, int index, private static void insertCredential(CompromisedCredential[] credentials, int index,
String signonRealm, GURL origin, String username, String displayOrigin, String signonRealm, GURL origin, String username, String displayOrigin,
String displayUsername, String password, String passwordChangeUrl, String associatedApp, String displayUsername, String password, String passwordChangeUrl, String associatedApp,
long creationTime, boolean leaked, boolean phished, boolean hasScript, long creationTime, boolean leaked, boolean phished, boolean hasStartableScript,
boolean hasAutoChangeButton) { boolean hasAutoChangeButton) {
credentials[index] = new CompromisedCredential(signonRealm, origin, username, displayOrigin, credentials[index] = new CompromisedCredential(signonRealm, origin, username, displayOrigin,
displayUsername, password, passwordChangeUrl, associatedApp, creationTime, leaked, displayUsername, password, passwordChangeUrl, associatedApp, creationTime, leaked,
phished, hasScript, hasAutoChangeButton); phished, hasStartableScript, hasAutoChangeButton);
} }
/** /**
......
...@@ -35,12 +35,12 @@ public class CompromisedCredential implements Parcelable { ...@@ -35,12 +35,12 @@ public class CompromisedCredential implements Parcelable {
in.readBooleanArray(boolArguments); in.readBooleanArray(boolArguments);
final boolean leaked = boolArguments[0]; final boolean leaked = boolArguments[0];
final boolean phished = boolArguments[1]; final boolean phished = boolArguments[1];
final boolean hasScript = boolArguments[2]; final boolean hasStartableScript = boolArguments[2];
final boolean hasAutoChangeButton = boolArguments[3]; final boolean hasAutoChangeButton = boolArguments[3];
return new CompromisedCredential(signonRealm, origin, username, displayOrigin, return new CompromisedCredential(signonRealm, origin, username, displayOrigin,
displayUsername, password, passwordChangeUrl, associatedApp, displayUsername, password, passwordChangeUrl, associatedApp,
creationTime, leaked, phished, hasScript, hasAutoChangeButton); creationTime, leaked, phished, hasStartableScript, hasAutoChangeButton);
} }
@Override @Override
...@@ -60,7 +60,7 @@ public class CompromisedCredential implements Parcelable { ...@@ -60,7 +60,7 @@ public class CompromisedCredential implements Parcelable {
private final long mCreationTime; private final long mCreationTime;
private final boolean mLeaked; private final boolean mLeaked;
private final boolean mPhished; private final boolean mPhished;
private final boolean mHasScript; private final boolean mHasStartableScript;
private final boolean mHasAutoChangeButton; private final boolean mHasAutoChangeButton;
/** /**
...@@ -77,14 +77,15 @@ public class CompromisedCredential implements Parcelable { ...@@ -77,14 +77,15 @@ public class CompromisedCredential implements Parcelable {
* time at which the compromised credential was first found to be compromised during * time at which the compromised credential was first found to be compromised during
* a check. * a check.
* @param phished True iff the credential was entered on an unsafe site. * @param phished True iff the credential was entered on an unsafe site.
* @param hasScript True iff there is a script to automatically fix the credential. * @param hasStartableScript True iff there is a script to automatically fix the credential and
* it can be started (username is not empty, password sync is on, etc.)
* @param hasAutoChangeButton True iff the button to automatically change the credential should * @param hasAutoChangeButton True iff the button to automatically change the credential should
* be shown. * be shown.
*/ */
public CompromisedCredential(String signonRealm, GURL origin, String username, public CompromisedCredential(String signonRealm, GURL origin, String username,
String displayOrigin, String displayUsername, String password, String passwordChangeUrl, String displayOrigin, String displayUsername, String password, String passwordChangeUrl,
String associatedApp, long creationTime, boolean leaked, boolean phished, String associatedApp, long creationTime, boolean leaked, boolean phished,
boolean hasScript, boolean hasAutoChangeButton) { boolean hasStartableScript, boolean hasAutoChangeButton) {
assert origin != null : "Credential origin is null! Pass an empty one instead."; assert origin != null : "Credential origin is null! Pass an empty one instead.";
assert signonRealm != null; assert signonRealm != null;
assert passwordChangeUrl != null : "Change URL may be empty but not null!"; assert passwordChangeUrl != null : "Change URL may be empty but not null!";
...@@ -93,8 +94,9 @@ public class CompromisedCredential implements Parcelable { ...@@ -93,8 +94,9 @@ public class CompromisedCredential implements Parcelable {
|| !associatedApp.isEmpty() || !associatedApp.isEmpty()
: "Change URL and app name may not be empty at the same time!"; : "Change URL and app name may not be empty at the same time!";
assert leaked || phished : "A compromised credential must be leaked or phished!"; assert leaked || phished : "A compromised credential must be leaked or phished!";
assert hasScript assert hasStartableScript
|| !hasAutoChangeButton : "Auto change button cannot be shown without a script!"; || !hasAutoChangeButton
: "Auto change button cannot be shown without a script that can start!";
mSignonRealm = signonRealm; mSignonRealm = signonRealm;
mOrigin = origin; mOrigin = origin;
mUsername = username; mUsername = username;
...@@ -106,7 +108,7 @@ public class CompromisedCredential implements Parcelable { ...@@ -106,7 +108,7 @@ public class CompromisedCredential implements Parcelable {
mCreationTime = creationTime; mCreationTime = creationTime;
mLeaked = leaked; mLeaked = leaked;
mPhished = phished; mPhished = phished;
mHasScript = hasScript; mHasStartableScript = hasStartableScript;
mHasAutoChangeButton = hasAutoChangeButton; mHasAutoChangeButton = hasAutoChangeButton;
} }
...@@ -147,8 +149,8 @@ public class CompromisedCredential implements Parcelable { ...@@ -147,8 +149,8 @@ public class CompromisedCredential implements Parcelable {
public boolean isPhished() { public boolean isPhished() {
return mPhished; return mPhished;
} }
public boolean hasScript() { public boolean hasStartableScript() {
return mHasScript; return mHasStartableScript;
} }
public boolean hasAutoChangeButton() { public boolean hasAutoChangeButton() {
return mHasAutoChangeButton; return mHasAutoChangeButton;
...@@ -166,7 +168,7 @@ public class CompromisedCredential implements Parcelable { ...@@ -166,7 +168,7 @@ public class CompromisedCredential implements Parcelable {
&& mPasswordChangeUrl.equals(that.mPasswordChangeUrl) && mPasswordChangeUrl.equals(that.mPasswordChangeUrl)
&& mAssociatedApp.equals(that.mAssociatedApp) && mCreationTime == that.mCreationTime && mAssociatedApp.equals(that.mAssociatedApp) && mCreationTime == that.mCreationTime
&& mLeaked == that.mLeaked && mPhished == that.mPhished && mLeaked == that.mLeaked && mPhished == that.mPhished
&& mHasScript == that.mHasScript && mHasStartableScript == that.mHasStartableScript
&& mHasAutoChangeButton == that.mHasAutoChangeButton; && mHasAutoChangeButton == that.mHasAutoChangeButton;
} }
...@@ -178,7 +180,7 @@ public class CompromisedCredential implements Parcelable { ...@@ -178,7 +180,7 @@ public class CompromisedCredential implements Parcelable {
+ ", displayUsername='" + mDisplayUsername + '\'' + ", password='" + mPassword + ", displayUsername='" + mDisplayUsername + '\'' + ", password='" + mPassword
+ '\'' + ", passwordChangeUrl='" + mPasswordChangeUrl + '\'' + ", associatedApp='" + '\'' + ", passwordChangeUrl='" + mPasswordChangeUrl + '\'' + ", associatedApp='"
+ mAssociatedApp + '\'' + ", creationTime=" + mCreationTime + ", leaked=" + mLeaked + mAssociatedApp + '\'' + ", creationTime=" + mCreationTime + ", leaked=" + mLeaked
+ ", phished=" + mPhished + ", hasScript=" + mHasScript + ", phished=" + mPhished + ", hasStartableScript=" + mHasStartableScript
+ ", hasAutoChangeButton=" + mHasAutoChangeButton + '}'; + ", hasAutoChangeButton=" + mHasAutoChangeButton + '}';
} }
...@@ -186,7 +188,7 @@ public class CompromisedCredential implements Parcelable { ...@@ -186,7 +188,7 @@ public class CompromisedCredential implements Parcelable {
public int hashCode() { public int hashCode() {
return Objects.hash(mSignonRealm, mOrigin.getPossiblyInvalidSpec(), mUsername, return Objects.hash(mSignonRealm, mOrigin.getPossiblyInvalidSpec(), mUsername,
mDisplayOrigin, mDisplayUsername, mPassword, mPasswordChangeUrl, mAssociatedApp, mDisplayOrigin, mDisplayUsername, mPassword, mPasswordChangeUrl, mAssociatedApp,
mCreationTime, mLeaked, mPhished, mHasScript, mHasAutoChangeButton); mCreationTime, mLeaked, mPhished, mHasStartableScript, mHasAutoChangeButton);
} }
@Override @Override
...@@ -201,7 +203,7 @@ public class CompromisedCredential implements Parcelable { ...@@ -201,7 +203,7 @@ public class CompromisedCredential implements Parcelable {
parcel.writeString(mAssociatedApp); parcel.writeString(mAssociatedApp);
parcel.writeLong(mCreationTime); parcel.writeLong(mCreationTime);
parcel.writeBooleanArray( parcel.writeBooleanArray(
new boolean[] {mLeaked, mPhished, mHasScript, mHasAutoChangeButton}); new boolean[] {mLeaked, mPhished, mHasStartableScript, mHasAutoChangeButton});
} }
@Override @Override
......
...@@ -25,7 +25,7 @@ public final class PasswordCheckMetricsRecorder { ...@@ -25,7 +25,7 @@ public final class PasswordCheckMetricsRecorder {
public static void recordCheckResolutionAction( public static void recordCheckResolutionAction(
@PasswordCheckResolutionAction int action, CompromisedCredential credential) { @PasswordCheckResolutionAction int action, CompromisedCredential credential) {
if (credential.hasScript()) { if (credential.hasStartableScript()) {
RecordHistogram.recordEnumeratedHistogram( RecordHistogram.recordEnumeratedHistogram(
"PasswordManager.AutomaticChange.ForSitesWithScripts", action, "PasswordManager.AutomaticChange.ForSitesWithScripts", action,
PasswordCheckResolutionAction.COUNT); PasswordCheckResolutionAction.COUNT);
......
...@@ -90,7 +90,7 @@ void PasswordCheckBridge::GetCompromisedCredentials( ...@@ -90,7 +90,7 @@ void PasswordCheckBridge::GetCompromisedCredentials(
password_manager::InsecureCredentialTypeFlags::kCredentialLeaked), password_manager::InsecureCredentialTypeFlags::kCredentialLeaked),
(credential.insecure_type == (credential.insecure_type ==
password_manager::InsecureCredentialTypeFlags::kCredentialPhished), password_manager::InsecureCredentialTypeFlags::kCredentialPhished),
credential.has_script, credential.has_auto_change_button); credential.has_startable_script, credential.has_auto_change_button);
} }
} }
......
...@@ -72,7 +72,8 @@ PasswordCheckManager::PasswordCheckManager(Profile* profile, Observer* observer) ...@@ -72,7 +72,8 @@ PasswordCheckManager::PasswordCheckManager(Profile* profile, Observer* observer)
// empty list. // empty list.
saved_passwords_presenter_.Init(); saved_passwords_presenter_.Init();
insecure_credentials_manager_.Init(); insecure_credentials_manager_.Init();
if (!ShouldOfferAutomaticPasswordChange()) {
if (!ShouldFetchPasswordScripts()) {
// Ensure that scripts are treated as initialized if they are unnecessary. // Ensure that scripts are treated as initialized if they are unnecessary.
FulfillPrecondition(kScriptsCachePrewarmed); FulfillPrecondition(kScriptsCachePrewarmed);
} }
...@@ -224,13 +225,14 @@ CompromisedCredentialForUI PasswordCheckManager::MakeUICredential( ...@@ -224,13 +225,14 @@ CompromisedCredentialForUI PasswordCheckManager::MakeUICredential(
credential.signon_realm); credential.signon_realm);
ui_credential.display_username = GetDisplayUsername(credential.username); ui_credential.display_username = GetDisplayUsername(credential.username);
ui_credential.has_script = ui_credential.has_startable_script =
!credential.username.empty() && ShouldOfferAutomaticPasswordChange() && !credential.username.empty() && ShouldFetchPasswordScripts() &&
password_script_fetcher_->IsScriptAvailable( password_script_fetcher_->IsScriptAvailable(
url::Origin::Create(credential.url.GetOrigin())); url::Origin::Create(credential.url.GetOrigin()));
// TODO(crbug.com/1132230): Implement separate logic for scripts fetching and ui_credential.has_auto_change_button =
// auto buttons. For now, has_auto_change_button <=> has_script. ui_credential.has_startable_script &&
ui_credential.has_auto_change_button = ui_credential.has_script; base::FeatureList::IsEnabled(
password_manager::features::kPasswordChangeInSettings);
if (facet.IsValidAndroidFacetURI()) { if (facet.IsValidAndroidFacetURI()) {
const PasswordForm& android_form = const PasswordForm& android_form =
...@@ -305,7 +307,7 @@ bool PasswordCheckManager::AreScriptsRefreshed() const { ...@@ -305,7 +307,7 @@ bool PasswordCheckManager::AreScriptsRefreshed() const {
} }
void PasswordCheckManager::RefreshScripts() { void PasswordCheckManager::RefreshScripts() {
if (!ShouldOfferAutomaticPasswordChange()) { if (!ShouldFetchPasswordScripts()) {
FulfillPrecondition(kScriptsCachePrewarmed); FulfillPrecondition(kScriptsCachePrewarmed);
return; return;
} }
...@@ -327,7 +329,7 @@ void PasswordCheckManager::OnScriptsFetched() { ...@@ -327,7 +329,7 @@ void PasswordCheckManager::OnScriptsFetched() {
} }
} }
bool PasswordCheckManager::ShouldOfferAutomaticPasswordChange() const { bool PasswordCheckManager::ShouldFetchPasswordScripts() const {
SyncState sync_state = password_manager_util::GetPasswordSyncState( SyncState sync_state = password_manager_util::GetPasswordSyncState(
ProfileSyncServiceFactory::GetForProfile(profile_)); ProfileSyncServiceFactory::GetForProfile(profile_));
...@@ -338,7 +340,7 @@ bool PasswordCheckManager::ShouldOfferAutomaticPasswordChange() const { ...@@ -338,7 +340,7 @@ bool PasswordCheckManager::ShouldOfferAutomaticPasswordChange() const {
} }
return base::FeatureList::IsEnabled( return base::FeatureList::IsEnabled(
password_manager::features::kPasswordChangeInSettings); password_manager::features::kPasswordScriptsFetching);
} }
bool PasswordCheckManager::IsPreconditionFulfilled( bool PasswordCheckManager::IsPreconditionFulfilled(
......
...@@ -51,7 +51,7 @@ class PasswordCheckManager ...@@ -51,7 +51,7 @@ class PasswordCheckManager
base::string16 display_origin; base::string16 display_origin;
std::string package_name; std::string package_name;
std::string change_password_url; std::string change_password_url;
bool has_script = false; bool has_startable_script = false;
bool has_auto_change_button = false; bool has_auto_change_button = false;
}; };
...@@ -183,10 +183,11 @@ class PasswordCheckManager ...@@ -183,10 +183,11 @@ class PasswordCheckManager
// in the account if the quota limit was reached. // in the account if the quota limit was reached.
bool CanUseAccountCheck() const; bool CanUseAccountCheck() const;
// Returns true if the automatic password change should be offered. // Returns true if the password scripts fetching (kPasswordScriptsFetching) is
// It should be offered only to sync users and who have // enabled. To have precise metrics about user actions on credentials with
// kPasswordChangeInSettings enabled. // scripts, scripts are fetched only for the users who can start a script,
bool ShouldOfferAutomaticPasswordChange() const; // i.e. sync users.
bool ShouldFetchPasswordScripts() const;
// Callback when PasswordScriptsFetcher's cache has been warmed up. // Callback when PasswordScriptsFetcher's cache has been warmed up.
void OnScriptsFetched(); void OnScriptsFetched();
......
...@@ -175,6 +175,7 @@ auto ExpectCompromisedCredentialForUI( ...@@ -175,6 +175,7 @@ auto ExpectCompromisedCredentialForUI(
const base::Optional<std::string>& package_name, const base::Optional<std::string>& package_name,
const base::Optional<std::string>& change_password_url, const base::Optional<std::string>& change_password_url,
InsecureCredentialTypeFlags insecure_type, InsecureCredentialTypeFlags insecure_type,
bool has_startable_script,
bool has_auto_change_button) { bool has_auto_change_button) {
auto package_name_field_matcher = auto package_name_field_matcher =
package_name.has_value() package_name.has_value()
...@@ -191,6 +192,8 @@ auto ExpectCompromisedCredentialForUI( ...@@ -191,6 +192,8 @@ auto ExpectCompromisedCredentialForUI(
Field(&CompromisedCredentialForUI::display_origin, display_origin), Field(&CompromisedCredentialForUI::display_origin, display_origin),
package_name_field_matcher, change_password_url_field_matcher, package_name_field_matcher, change_password_url_field_matcher,
Field(&CompromisedCredentialForUI::insecure_type, insecure_type), Field(&CompromisedCredentialForUI::insecure_type, insecure_type),
Field(&CompromisedCredentialForUI::has_startable_script,
has_startable_script),
Field(&CompromisedCredentialForUI::has_auto_change_button, Field(&CompromisedCredentialForUI::has_auto_change_button,
has_auto_change_button)); has_auto_change_button));
} }
...@@ -291,8 +294,10 @@ TEST_F(PasswordCheckManagerTest, ...@@ -291,8 +294,10 @@ TEST_F(PasswordCheckManagerTest,
RunCheckAfterLastInitializationAutomaticChangeOn) { RunCheckAfterLastInitializationAutomaticChangeOn) {
// Enable password sync // Enable password sync
sync_service().SetActiveDataTypes(syncer::ModelTypeSet(syncer::PASSWORDS)); sync_service().SetActiveDataTypes(syncer::ModelTypeSet(syncer::PASSWORDS));
feature_list().InitAndEnableFeature( feature_list().InitWithFeatures(
password_manager::features::kPasswordChangeInSettings); {password_manager::features::kPasswordScriptsFetching,
password_manager::features::kPasswordChangeInSettings},
{});
EXPECT_CALL(mock_observer(), OnPasswordCheckStatusChanged).Times(AtLeast(1)); EXPECT_CALL(mock_observer(), OnPasswordCheckStatusChanged).Times(AtLeast(1));
EXPECT_CALL(mock_observer(), OnSavedPasswordsFetched(1)); EXPECT_CALL(mock_observer(), OnSavedPasswordsFetched(1));
store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1)); store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
...@@ -331,6 +336,7 @@ TEST_F(PasswordCheckManagerTest, CorrectlyCreatesUIStructForSiteCredential) { ...@@ -331,6 +336,7 @@ TEST_F(PasswordCheckManagerTest, CorrectlyCreatesUIStructForSiteCredential) {
base::ASCIIToUTF16(kUsername1), base::ASCIIToUTF16("example.com"), base::ASCIIToUTF16(kUsername1), base::ASCIIToUTF16("example.com"),
base::nullopt, "https://example.com/", base::nullopt, "https://example.com/",
InsecureCredentialTypeFlags::kCredentialLeaked, InsecureCredentialTypeFlags::kCredentialLeaked,
/*has_startable_script=*/false,
/*has_auto_change_button=*/false))); /*has_auto_change_button=*/false)));
} }
...@@ -355,11 +361,13 @@ TEST_F(PasswordCheckManagerTest, CorrectlyCreatesUIStructForAppCredentials) { ...@@ -355,11 +361,13 @@ TEST_F(PasswordCheckManagerTest, CorrectlyCreatesUIStructForAppCredentials) {
base::ASCIIToUTF16(kUsername1), base::ASCIIToUTF16(kUsername1),
base::ASCIIToUTF16("App (com.example.app)"), "com.example.app", base::ASCIIToUTF16("App (com.example.app)"), "com.example.app",
base::nullopt, InsecureCredentialTypeFlags::kCredentialLeaked, base::nullopt, InsecureCredentialTypeFlags::kCredentialLeaked,
/*has_startable_script=*/false,
/*has_auto_change_button=*/false), /*has_auto_change_button=*/false),
ExpectCompromisedCredentialForUI( ExpectCompromisedCredentialForUI(
base::ASCIIToUTF16(kUsername2), base::ASCIIToUTF16("Example App"), base::ASCIIToUTF16(kUsername2), base::ASCIIToUTF16("Example App"),
"com.example.app", base::nullopt, "com.example.app", base::nullopt,
InsecureCredentialTypeFlags::kCredentialLeaked, InsecureCredentialTypeFlags::kCredentialLeaked,
/*has_startable_script=*/false,
/*has_auto_change_button=*/false))); /*has_auto_change_button=*/false)));
} }
...@@ -394,22 +402,28 @@ TEST_F(PasswordCheckManagerTest, ...@@ -394,22 +402,28 @@ TEST_F(PasswordCheckManagerTest,
InitializeManager(); InitializeManager();
// Disable password sync // Disable password sync
sync_service().SetActiveDataTypes(syncer::ModelTypeSet()); sync_service().SetActiveDataTypes(syncer::ModelTypeSet());
feature_list().InitAndEnableFeature( feature_list().InitWithFeatures(
password_manager::features::kPasswordChangeInSettings); {password_manager::features::kPasswordScriptsFetching,
password_manager::features::kPasswordChangeInSettings},
{});
store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1)); store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
store().AddCompromisedCredentials(MakeCompromised(kExampleCom, kUsername1)); store().AddCompromisedCredentials(MakeCompromised(kExampleCom, kUsername1));
RunUntilIdle(); RunUntilIdle();
// To have precise metrics, scripts are not requested for users who cannot
// start a script, i.e. non-sync users.
EXPECT_CALL(fetcher(), RefreshScriptsIfNecessary).Times(0); EXPECT_CALL(fetcher(), RefreshScriptsIfNecessary).Times(0);
manager().RefreshScripts(); manager().RefreshScripts();
EXPECT_CALL(fetcher(), IsScriptAvailable).Times(0);
EXPECT_THAT( EXPECT_THAT(
manager().GetCompromisedCredentials(), manager().GetCompromisedCredentials(),
ElementsAre(ExpectCompromisedCredentialForUI( ElementsAre(ExpectCompromisedCredentialForUI(
base::ASCIIToUTF16(kUsername1), base::ASCIIToUTF16("example.com"), base::ASCIIToUTF16(kUsername1), base::ASCIIToUTF16("example.com"),
base::nullopt, "https://example.com/", base::nullopt, "https://example.com/",
InsecureCredentialTypeFlags::kCredentialLeaked, InsecureCredentialTypeFlags::kCredentialLeaked,
/*has_startable_script=*/false,
/*has_auto_change_button=*/false))); /*has_auto_change_button=*/false)));
} }
...@@ -418,8 +432,10 @@ TEST_F(PasswordCheckManagerTest, ...@@ -418,8 +432,10 @@ TEST_F(PasswordCheckManagerTest,
InitializeManager(); InitializeManager();
// Enable password sync // Enable password sync
sync_service().SetActiveDataTypes(syncer::ModelTypeSet(syncer::PASSWORDS)); sync_service().SetActiveDataTypes(syncer::ModelTypeSet(syncer::PASSWORDS));
feature_list().InitAndEnableFeature( feature_list().InitWithFeatures(
password_manager::features::kPasswordChangeInSettings); {password_manager::features::kPasswordScriptsFetching,
password_manager::features::kPasswordChangeInSettings},
{});
store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1)); store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
store().AddCompromisedCredentials(MakeCompromised(kExampleCom, kUsername1)); store().AddCompromisedCredentials(MakeCompromised(kExampleCom, kUsername1));
...@@ -430,13 +446,14 @@ TEST_F(PasswordCheckManagerTest, ...@@ -430,13 +446,14 @@ TEST_F(PasswordCheckManagerTest,
manager().RefreshScripts(); manager().RefreshScripts();
EXPECT_CALL(fetcher(), IsScriptAvailable).WillRepeatedly(Return(true)); EXPECT_CALL(fetcher(), IsScriptAvailable).WillOnce(Return(true));
EXPECT_THAT( EXPECT_THAT(
manager().GetCompromisedCredentials(), manager().GetCompromisedCredentials(),
ElementsAre(ExpectCompromisedCredentialForUI( ElementsAre(ExpectCompromisedCredentialForUI(
base::ASCIIToUTF16(kUsername1), base::ASCIIToUTF16("example.com"), base::ASCIIToUTF16(kUsername1), base::ASCIIToUTF16("example.com"),
base::nullopt, "https://example.com/", base::nullopt, "https://example.com/",
InsecureCredentialTypeFlags::kCredentialLeaked, InsecureCredentialTypeFlags::kCredentialLeaked,
/*has_startable_script=*/true,
/*has_auto_change_button=*/true))); /*has_auto_change_button=*/true)));
} }
...@@ -445,8 +462,10 @@ TEST_F(PasswordCheckManagerTest, ...@@ -445,8 +462,10 @@ TEST_F(PasswordCheckManagerTest,
InitializeManager(); InitializeManager();
// Enable password sync // Enable password sync
sync_service().SetActiveDataTypes(syncer::ModelTypeSet(syncer::PASSWORDS)); sync_service().SetActiveDataTypes(syncer::ModelTypeSet(syncer::PASSWORDS));
feature_list().InitAndEnableFeature( feature_list().InitWithFeatures(
password_manager::features::kPasswordChangeInSettings); {password_manager::features::kPasswordScriptsFetching,
password_manager::features::kPasswordChangeInSettings},
{});
store().AddLogin(MakeSavedPassword(kExampleCom, "")); store().AddLogin(MakeSavedPassword(kExampleCom, ""));
store().AddCompromisedCredentials(MakeCompromised(kExampleCom, "")); store().AddCompromisedCredentials(MakeCompromised(kExampleCom, ""));
...@@ -457,13 +476,80 @@ TEST_F(PasswordCheckManagerTest, ...@@ -457,13 +476,80 @@ TEST_F(PasswordCheckManagerTest,
manager().RefreshScripts(); manager().RefreshScripts();
// Scripts are not offered if username is empty. // Particular script availability is not requested as a script cannot be
// started with an empty username.
EXPECT_CALL(fetcher(), IsScriptAvailable).Times(0);
EXPECT_THAT( EXPECT_THAT(
manager().GetCompromisedCredentials(), manager().GetCompromisedCredentials(),
ElementsAre(ExpectCompromisedCredentialForUI( ElementsAre(ExpectCompromisedCredentialForUI(
base::ASCIIToUTF16("No username"), base::ASCIIToUTF16("example.com"), base::ASCIIToUTF16("No username"), base::ASCIIToUTF16("example.com"),
base::nullopt, "https://example.com/", base::nullopt, "https://example.com/",
InsecureCredentialTypeFlags::kCredentialLeaked, InsecureCredentialTypeFlags::kCredentialLeaked,
/*has_startable_script=*/false,
/*has_auto_change_button=*/false)));
}
TEST_F(PasswordCheckManagerTest,
CorrectlyCreatesUIStructWithScriptsFetchingButAutomaticChangeOff) {
InitializeManager();
// Enable password sync
sync_service().SetActiveDataTypes(syncer::ModelTypeSet(syncer::PASSWORDS));
feature_list().InitWithFeatures(
/*enabled_features=*/{password_manager::features::
kPasswordScriptsFetching},
/*disabled_features=*/{
password_manager::features::kPasswordChangeInSettings});
store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
store().AddCompromisedCredentials(MakeCompromised(kExampleCom, kUsername1));
RunUntilIdle();
EXPECT_CALL(fetcher(), RefreshScriptsIfNecessary)
.WillOnce(Invoke(
[](base::OnceClosure callback) { std::move(callback).Run(); }));
manager().RefreshScripts();
// A script is available but an auto change button is not shown because
// |kPasswordChangeInSettings| is disabled.
EXPECT_CALL(fetcher(), IsScriptAvailable).WillOnce(Return(true));
EXPECT_THAT(
manager().GetCompromisedCredentials(),
ElementsAre(ExpectCompromisedCredentialForUI(
base::ASCIIToUTF16(kUsername1), base::ASCIIToUTF16("example.com"),
base::nullopt, "https://example.com/",
InsecureCredentialTypeFlags::kCredentialLeaked,
/*has_startable_script=*/true,
/*has_auto_change_button=*/false)));
}
TEST_F(PasswordCheckManagerTest,
CorrectlyCreatesUIStructWithScriptsFetchingButNoAvailableScript) {
InitializeManager();
// Enable password sync
sync_service().SetActiveDataTypes(syncer::ModelTypeSet(syncer::PASSWORDS));
feature_list().InitWithFeatures(
{password_manager::features::kPasswordScriptsFetching,
password_manager::features::kPasswordChangeInSettings},
{});
store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
store().AddCompromisedCredentials(MakeCompromised(kExampleCom, kUsername1));
RunUntilIdle();
EXPECT_CALL(fetcher(), RefreshScriptsIfNecessary)
.WillOnce(Invoke(
[](base::OnceClosure callback) { std::move(callback).Run(); }));
manager().RefreshScripts();
// A script is not available and therefore no auto change button is shown.
EXPECT_CALL(fetcher(), IsScriptAvailable).WillOnce(Return(false));
EXPECT_THAT(
manager().GetCompromisedCredentials(),
ElementsAre(ExpectCompromisedCredentialForUI(
base::ASCIIToUTF16(kUsername1), base::ASCIIToUTF16("example.com"),
base::nullopt, "https://example.com/",
InsecureCredentialTypeFlags::kCredentialLeaked,
/*has_startable_script=*/false,
/*has_auto_change_button=*/false))); /*has_auto_change_button=*/false)));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment