Commit 9063ba57 authored by Friedrich Horschig's avatar Friedrich Horschig Committed by Commit Bot

[PwdCheckAndroid] Check is started automatically and on restart

With this CL, the check is automatically started if a user clicks the
restart button or navigates to the password check page from a
non-safety check origin.

The check is run to completion unless all observers unsubscribe before
the end of the check (e.g. because their surface is closed).

Promoted bugs:
 * List receives full update for each new credential
 * The "last run" date range does not seem sensible

Bug: 1109691, 1092444
Change-Id: Icfb25b91508d36b938e56cea2516922089963de2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2346387
Commit-Queue: Ioana Pandele <ioanap@chromium.org>
Reviewed-by: default avatarIoana Pandele <ioanap@chromium.org>
Cr-Commit-Position: refs/heads/master@{#796777}
parent b67c8f63
...@@ -90,6 +90,12 @@ class PasswordCheckCoordinator implements PasswordCheckComponentUi, LifecycleObs ...@@ -90,6 +90,12 @@ class PasswordCheckCoordinator implements PasswordCheckComponentUi, LifecycleObs
} }
} }
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void stopCheck() {
PasswordCheck check = PasswordCheckFactory.getPasswordCheckInstance();
if (check != null) check.stopCheck();
}
// TODO(crbug.com/1101256): Move to view code. // TODO(crbug.com/1101256): Move to view code.
@Override @Override
public boolean handleHelp(MenuItem item) { public boolean handleHelp(MenuItem item) {
......
...@@ -36,6 +36,7 @@ class PasswordCheckImpl implements PasswordCheck, PasswordCheckObserver { ...@@ -36,6 +36,7 @@ class PasswordCheckImpl implements PasswordCheck, PasswordCheckObserver {
fragmentArgs.putInt( fragmentArgs.putInt(
PasswordCheckFragmentView.PASSWORD_CHECK_REFERRER, passwordCheckReferrer); PasswordCheckFragmentView.PASSWORD_CHECK_REFERRER, passwordCheckReferrer);
launcher.launchSettingsActivity(context, PasswordCheckFragmentView.class, fragmentArgs); launcher.launchSettingsActivity(context, PasswordCheckFragmentView.class, fragmentArgs);
if (passwordCheckReferrer != PasswordCheckReferrer.SAFETY_CHECK) startCheck();
} }
@Override @Override
......
...@@ -12,6 +12,7 @@ import static org.chromium.chrome.browser.password_check.PasswordCheckProperties ...@@ -12,6 +12,7 @@ import static org.chromium.chrome.browser.password_check.PasswordCheckProperties
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.CHECK_STATUS; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.CHECK_STATUS;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.CHECK_TIMESTAMP; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.CHECK_TIMESTAMP;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.COMPROMISED_CREDENTIALS_COUNT; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.COMPROMISED_CREDENTIALS_COUNT;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.RESTART_BUTTON_ACTION;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.UNKNOWN_PROGRESS; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.UNKNOWN_PROGRESS;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.ITEMS; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.ITEMS;
...@@ -54,6 +55,7 @@ class PasswordCheckMediator ...@@ -54,6 +55,7 @@ class PasswordCheckMediator
.with(CHECK_STATUS, PasswordCheckUIStatus.RUNNING) .with(CHECK_STATUS, PasswordCheckUIStatus.RUNNING)
.with(CHECK_TIMESTAMP, null) .with(CHECK_TIMESTAMP, null)
.with(COMPROMISED_CREDENTIALS_COUNT, null) .with(COMPROMISED_CREDENTIALS_COUNT, null)
.with(RESTART_BUTTON_ACTION, this::runCheck)
.build())); .build()));
getPasswordCheck().addObserver(this, true); getPasswordCheck().addObserver(this, true);
} }
...@@ -71,6 +73,7 @@ class PasswordCheckMediator ...@@ -71,6 +73,7 @@ class PasswordCheckMediator
items.add(new ListItem(PasswordCheckProperties.ItemType.HEADER, items.add(new ListItem(PasswordCheckProperties.ItemType.HEADER,
new PropertyModel.Builder(PasswordCheckProperties.HeaderProperties.ALL_KEYS) new PropertyModel.Builder(PasswordCheckProperties.HeaderProperties.ALL_KEYS)
.with(CHECK_STATUS, PasswordCheckUIStatus.RUNNING) .with(CHECK_STATUS, PasswordCheckUIStatus.RUNNING)
.with(RESTART_BUTTON_ACTION, this::runCheck)
.build())); .build()));
} }
...@@ -179,6 +182,10 @@ class PasswordCheckMediator ...@@ -179,6 +182,10 @@ class PasswordCheckMediator
mLaunchCctWithScript.accept(credential); mLaunchCctWithScript.accept(credential);
} }
private void runCheck() {
getPasswordCheck().startCheck();
}
private PasswordCheck getPasswordCheck() { private PasswordCheck getPasswordCheck() {
PasswordCheck passwordCheck = PasswordCheckFactory.getOrCreate(); PasswordCheck passwordCheck = PasswordCheckFactory.getOrCreate();
assert passwordCheck != null : "Password Check UI component needs native counterpart!"; assert passwordCheck != null : "Password Check UI component needs native counterpart!";
......
...@@ -64,9 +64,11 @@ class PasswordCheckProperties { ...@@ -64,9 +64,11 @@ class PasswordCheckProperties {
static final PropertyModel static final PropertyModel
.WritableObjectPropertyKey<Integer> COMPROMISED_CREDENTIALS_COUNT = .WritableObjectPropertyKey<Integer> COMPROMISED_CREDENTIALS_COUNT =
new PropertyModel.WritableObjectPropertyKey<>("compromised_credentials_count"); new PropertyModel.WritableObjectPropertyKey<>("compromised_credentials_count");
static final PropertyModel.ReadableObjectPropertyKey<Runnable> RESTART_BUTTON_ACTION =
new PropertyModel.WritableObjectPropertyKey<>("restart_button_action");
static final PropertyKey[] ALL_KEYS = { static final PropertyKey[] ALL_KEYS = {CHECK_PROGRESS, CHECK_STATUS, CHECK_TIMESTAMP,
CHECK_PROGRESS, CHECK_STATUS, CHECK_TIMESTAMP, COMPROMISED_CREDENTIALS_COUNT}; COMPROMISED_CREDENTIALS_COUNT, RESTART_BUTTON_ACTION};
static final Pair<Integer, Integer> UNKNOWN_PROGRESS = new Pair<>(-1, -1); static final Pair<Integer, Integer> UNKNOWN_PROGRESS = new Pair<>(-1, -1);
......
...@@ -12,6 +12,7 @@ import static org.chromium.chrome.browser.password_check.PasswordCheckProperties ...@@ -12,6 +12,7 @@ import static org.chromium.chrome.browser.password_check.PasswordCheckProperties
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.CHECK_STATUS; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.CHECK_STATUS;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.CHECK_TIMESTAMP; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.CHECK_TIMESTAMP;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.COMPROMISED_CREDENTIALS_COUNT; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.COMPROMISED_CREDENTIALS_COUNT;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.RESTART_BUTTON_ACTION;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.UNKNOWN_PROGRESS; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.UNKNOWN_PROGRESS;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.ITEMS; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.ITEMS;
import static org.chromium.components.embedder_support.util.UrlUtilities.stripScheme; import static org.chromium.components.embedder_support.util.UrlUtilities.stripScheme;
...@@ -178,7 +179,7 @@ class PasswordCheckViewBinder { ...@@ -178,7 +179,7 @@ class PasswordCheckViewBinder {
if (key == CHECK_PROGRESS) { if (key == CHECK_PROGRESS) {
updateStatusText(view, status, compromisedCredentialsCount, checkTimestamp, progress); updateStatusText(view, status, compromisedCredentialsCount, checkTimestamp, progress);
} else if (key == CHECK_STATUS) { } else if (key == CHECK_STATUS) {
updateActionButton(view, status); updateActionButton(view, status, model.get(RESTART_BUTTON_ACTION));
updateStatusIcon(view, status, compromisedCredentialsCount); updateStatusIcon(view, status, compromisedCredentialsCount);
updateStatusIllustration(view, status, compromisedCredentialsCount); updateStatusIllustration(view, status, compromisedCredentialsCount);
updateStatusText(view, status, compromisedCredentialsCount, checkTimestamp, progress); updateStatusText(view, status, compromisedCredentialsCount, checkTimestamp, progress);
...@@ -190,6 +191,8 @@ class PasswordCheckViewBinder { ...@@ -190,6 +191,8 @@ class PasswordCheckViewBinder {
updateStatusIllustration(view, status, compromisedCredentialsCount); updateStatusIllustration(view, status, compromisedCredentialsCount);
updateStatusText(view, status, compromisedCredentialsCount, checkTimestamp, progress); updateStatusText(view, status, compromisedCredentialsCount, checkTimestamp, progress);
updateStatusSubtitle(view, status, compromisedCredentialsCount); updateStatusSubtitle(view, status, compromisedCredentialsCount);
} else if (key == RESTART_BUTTON_ACTION) {
assert model.get(RESTART_BUTTON_ACTION) != null : "Restart action is always required.";
} else { } else {
assert false : "Unhandled update to property:" + key; assert false : "Unhandled update to property:" + key;
} }
...@@ -197,15 +200,13 @@ class PasswordCheckViewBinder { ...@@ -197,15 +200,13 @@ class PasswordCheckViewBinder {
private PasswordCheckViewBinder() {} private PasswordCheckViewBinder() {}
private static void updateActionButton(View view, @PasswordCheckUIStatus int status) { private static void updateActionButton(
View view, @PasswordCheckUIStatus int status, Runnable startCheck) {
ImageButton restartButton = view.findViewById(R.id.check_status_restart_button); ImageButton restartButton = view.findViewById(R.id.check_status_restart_button);
if (status != PasswordCheckUIStatus.RUNNING) { if (status != PasswordCheckUIStatus.RUNNING) {
restartButton.setVisibility(View.VISIBLE); restartButton.setVisibility(View.VISIBLE);
restartButton.setClickable(true); restartButton.setClickable(true);
restartButton.setOnClickListener(unusedView restartButton.setOnClickListener(unusedView -> startCheck.run());
-> {
// TODO(crbug.com/1109691): Add call to restart the check.
});
} else { } else {
restartButton.setVisibility(View.GONE); restartButton.setVisibility(View.GONE);
restartButton.setClickable(false); restartButton.setClickable(false);
......
...@@ -29,6 +29,7 @@ import static org.chromium.chrome.browser.password_check.PasswordCheckProperties ...@@ -29,6 +29,7 @@ import static org.chromium.chrome.browser.password_check.PasswordCheckProperties
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.CHECK_STATUS; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.CHECK_STATUS;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.CHECK_TIMESTAMP; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.CHECK_TIMESTAMP;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.COMPROMISED_CREDENTIALS_COUNT; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.COMPROMISED_CREDENTIALS_COUNT;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.RESTART_BUTTON_ACTION;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.UNKNOWN_PROGRESS; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.UNKNOWN_PROGRESS;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.ITEMS; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.ITEMS;
import static org.chromium.chrome.browser.password_check.PasswordCheckUIStatus.ERROR_NO_PASSWORDS; import static org.chromium.chrome.browser.password_check.PasswordCheckUIStatus.ERROR_NO_PASSWORDS;
...@@ -112,6 +113,8 @@ public class PasswordCheckViewTest { ...@@ -112,6 +113,8 @@ public class PasswordCheckViewTest {
private PasswordCheckComponentUi mComponentUi; private PasswordCheckComponentUi mComponentUi;
@Mock @Mock
private PasswordCheckCoordinator.CredentialEventHandler mMockHandler; private PasswordCheckCoordinator.CredentialEventHandler mMockHandler;
@Mock
private Runnable mMockStartButtonCallback;
@Rule @Rule
public SettingsActivityTestRule<PasswordCheckFragmentView> mTestRule = public SettingsActivityTestRule<PasswordCheckFragmentView> mTestRule =
...@@ -219,13 +222,15 @@ public class PasswordCheckViewTest { ...@@ -219,13 +222,15 @@ public class PasswordCheckViewTest {
@Test @Test
@MediumTest @MediumTest
public void testStatusDisplaysRestartAction() { public void testStatusDisplaysClickableRestartAction() {
Long checkTimestamp = System.currentTimeMillis(); Long checkTimestamp = System.currentTimeMillis();
runOnUiThreadBlocking( runOnUiThreadBlocking(
() -> { mModel.get(ITEMS).add(buildHeader(IDLE, 0, checkTimestamp)); }); () -> { mModel.get(ITEMS).add(buildHeader(IDLE, 0, checkTimestamp)); });
waitForListViewToHaveLength(1); waitForListViewToHaveLength(1);
assertThat(getActionButton().getVisibility(), is(View.VISIBLE)); assertThat(getActionButton().getVisibility(), is(View.VISIBLE));
assertTrue(getActionButton().isClickable()); assertTrue(getActionButton().isClickable());
getActionButton().callOnClick();
waitForEvent(mMockStartButtonCallback).run();
} }
@Test @Test
...@@ -347,7 +352,7 @@ public class PasswordCheckViewTest { ...@@ -347,7 +352,7 @@ public class PasswordCheckViewTest {
@Test @Test
@MediumTest @MediumTest
public void testStatusDysplaysSubtitleOnIdleNoLeaks() { public void testStatusDisplaysSubtitleOnIdleNoLeaks() {
Long checkTimestamp = System.currentTimeMillis(); Long checkTimestamp = System.currentTimeMillis();
runOnUiThreadBlocking( runOnUiThreadBlocking(
() -> { mModel.get(ITEMS).add(buildHeader(IDLE, 0, checkTimestamp)); }); () -> { mModel.get(ITEMS).add(buildHeader(IDLE, 0, checkTimestamp)); });
...@@ -359,7 +364,7 @@ public class PasswordCheckViewTest { ...@@ -359,7 +364,7 @@ public class PasswordCheckViewTest {
@Test @Test
@MediumTest @MediumTest
public void testStatusDysplaysSubtitleOnIdleWithLeaks() { public void testStatusDisplaysSubtitleOnIdleWithLeaks() {
Long checkTimestamp = System.currentTimeMillis(); Long checkTimestamp = System.currentTimeMillis();
runOnUiThreadBlocking( runOnUiThreadBlocking(
() -> { mModel.get(ITEMS).add(buildHeader(IDLE, LEAKS_COUNT, checkTimestamp)); }); () -> { mModel.get(ITEMS).add(buildHeader(IDLE, LEAKS_COUNT, checkTimestamp)); });
...@@ -372,7 +377,7 @@ public class PasswordCheckViewTest { ...@@ -372,7 +377,7 @@ public class PasswordCheckViewTest {
@Test @Test
@MediumTest @MediumTest
public void testStatusNotDysplaysSubtitle() { public void testStatusNotDisplaysSubtitle() {
runOnUiThreadBlocking(() -> { mModel.get(ITEMS).add(buildHeader(ERROR_UNKNOWN)); }); runOnUiThreadBlocking(() -> { mModel.get(ITEMS).add(buildHeader(ERROR_UNKNOWN)); });
waitForListViewToHaveLength(1); waitForListViewToHaveLength(1);
assertThat(getHeaderSubtitle().getVisibility(), is(View.GONE)); assertThat(getHeaderSubtitle().getVisibility(), is(View.GONE));
...@@ -538,6 +543,7 @@ public class PasswordCheckViewTest { ...@@ -538,6 +543,7 @@ public class PasswordCheckViewTest {
.with(CHECK_STATUS, status) .with(CHECK_STATUS, status)
.with(CHECK_TIMESTAMP, checkTimestamp) .with(CHECK_TIMESTAMP, checkTimestamp)
.with(COMPROMISED_CREDENTIALS_COUNT, compromisedCredentialsCount) .with(COMPROMISED_CREDENTIALS_COUNT, compromisedCredentialsCount)
.with(RESTART_BUTTON_ACTION, mMockStartButtonCallback)
.build()); .build());
} }
......
...@@ -21,6 +21,7 @@ import static org.chromium.chrome.browser.password_check.PasswordCheckProperties ...@@ -21,6 +21,7 @@ import static org.chromium.chrome.browser.password_check.PasswordCheckProperties
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.CHECK_STATUS; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.CHECK_STATUS;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.CHECK_TIMESTAMP; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.CHECK_TIMESTAMP;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.COMPROMISED_CREDENTIALS_COUNT; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.COMPROMISED_CREDENTIALS_COUNT;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.RESTART_BUTTON_ACTION;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.UNKNOWN_PROGRESS; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.UNKNOWN_PROGRESS;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.ITEMS; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.ITEMS;
import static org.chromium.chrome.browser.password_check.PasswordCheckUIStatus.ERROR_OFFLINE; import static org.chromium.chrome.browser.password_check.PasswordCheckUIStatus.ERROR_OFFLINE;
...@@ -113,6 +114,7 @@ public class PasswordCheckControllerTest { ...@@ -113,6 +114,7 @@ public class PasswordCheckControllerTest {
ListModel<MVCListAdapter.ListItem> itemList = mModel.get(ITEMS); ListModel<MVCListAdapter.ListItem> itemList = mModel.get(ITEMS);
assertThat(itemList.get(0).type, is(ItemType.HEADER)); assertThat(itemList.get(0).type, is(ItemType.HEADER));
assertThat(itemList.get(0).model.get(CHECK_STATUS), is(IDLE)); assertThat(itemList.get(0).model.get(CHECK_STATUS), is(IDLE));
assertNotNull(itemList.get(0).model.get(RESTART_BUTTON_ACTION));
} }
@Test @Test
...@@ -203,6 +205,7 @@ public class PasswordCheckControllerTest { ...@@ -203,6 +205,7 @@ public class PasswordCheckControllerTest {
assertNull(header.model.get(CHECK_PROGRESS)); assertNull(header.model.get(CHECK_PROGRESS));
assertNotNull(header.model.get(CHECK_TIMESTAMP)); assertNotNull(header.model.get(CHECK_TIMESTAMP));
assertNotNull(header.model.get(COMPROMISED_CREDENTIALS_COUNT)); assertNotNull(header.model.get(COMPROMISED_CREDENTIALS_COUNT));
assertNotNull(header.model.get(RESTART_BUTTON_ACTION));
} }
private void assertRunningHeader( private void assertRunningHeader(
...@@ -211,11 +214,13 @@ public class PasswordCheckControllerTest { ...@@ -211,11 +214,13 @@ public class PasswordCheckControllerTest {
assertThat(header.model.get(CHECK_PROGRESS), is(progress)); assertThat(header.model.get(CHECK_PROGRESS), is(progress));
assertNull(header.model.get(CHECK_TIMESTAMP)); assertNull(header.model.get(CHECK_TIMESTAMP));
assertNull(header.model.get(COMPROMISED_CREDENTIALS_COUNT)); assertNull(header.model.get(COMPROMISED_CREDENTIALS_COUNT));
assertNotNull(header.model.get(RESTART_BUTTON_ACTION));
} }
private void assertHeaderTypeWithStatus( private void assertHeaderTypeWithStatus(
MVCListAdapter.ListItem header, @PasswordCheckUIStatus int status) { MVCListAdapter.ListItem header, @PasswordCheckUIStatus int status) {
assertThat(header.type, is(ItemType.HEADER)); assertThat(header.type, is(ItemType.HEADER));
assertThat(header.model.get(CHECK_STATUS), is(status)); assertThat(header.model.get(CHECK_STATUS), is(status));
assertNotNull(header.model.get(RESTART_BUTTON_ACTION));
} }
} }
...@@ -138,7 +138,11 @@ void PasswordCheckManager::OnStateChanged(State state) { ...@@ -138,7 +138,11 @@ void PasswordCheckManager::OnStateChanged(State state) {
void PasswordCheckManager::OnCredentialDone( void PasswordCheckManager::OnCredentialDone(
const password_manager::LeakCheckCredential& credential, const password_manager::LeakCheckCredential& credential,
password_manager::IsLeaked is_leaked) { password_manager::IsLeaked is_leaked) {
// TODO(crbug.com/1102025): implement this. // TODO(crbug.com/1092444): Advance progress.
if (is_leaked) {
// TODO(crbug.com/1092444): Trigger single-credential update.
compromised_credentials_manager_.SaveCompromisedCredential(credential);
}
} }
CompromisedCredentialForUI PasswordCheckManager::MakeUICredential( CompromisedCredentialForUI PasswordCheckManager::MakeUICredential(
......
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