Commit b27232d7 authored by Eleonora Rocchi's avatar Eleonora Rocchi Committed by Commit Bot

[PwdCheckAndroid] Add redirect to Google Password Check on quota limit

This CL adds the logic to redirect the user to the Google Password
Check on quota limit error. The redirect is called through
PasswordCheckBridge to avoid dependencies on chrome_java.

IDS_PASSWORD_CHECK_STATUS_MESSAGE_ERROR_QUOTA_LIMIT_ACCOUNT_CHECK.png
https://storage.cloud.google.com/chromium-translation-screenshots/c4546cf199aa6314ead807fa1fc0e1ed8b779a83

Bug: 1092444
Change-Id: I374ad088c305d299fea00f412f27dd6ab3d0e9b5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2362023Reviewed-by: default avatarIoana Pandele <ioanap@chromium.org>
Reviewed-by: default avatarFriedrich [CET] <fhorschig@chromium.org>
Commit-Queue: Eleonora Rocchi <erocchi@google.com>
Cr-Commit-Position: refs/heads/master@{#799117}
parent 83874a6f
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
package org.chromium.chrome.browser.password_manager; package org.chromium.chrome.browser.password_manager;
import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
...@@ -19,13 +20,11 @@ import org.chromium.ui.base.WindowAndroid; ...@@ -19,13 +20,11 @@ import org.chromium.ui.base.WindowAndroid;
*/ */
public class PasswordCheckupLauncher { public class PasswordCheckupLauncher {
@CalledByNative @CalledByNative
private static void launchCheckupInAccount(String checkupUrl, WindowAndroid windowAndroid) { private static void launchCheckupInAccountWithWindowAndroid(
String checkupUrl, WindowAndroid windowAndroid) {
if (windowAndroid.getContext().get() == null) return; // Window not available yet/anymore. if (windowAndroid.getContext().get() == null) return; // Window not available yet/anymore.
ChromeActivity activity = (ChromeActivity) windowAndroid.getActivity().get(); ChromeActivity activity = (ChromeActivity) windowAndroid.getActivity().get();
if (tryLaunchingNativePasswordCheckup(activity)) return; launchCheckupInAccountWithActivity(checkupUrl, activity);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(checkupUrl));
intent.setPackage(activity.getPackageName());
activity.startActivity(intent);
} }
@CalledByNative @CalledByNative
...@@ -36,7 +35,15 @@ public class PasswordCheckupLauncher { ...@@ -36,7 +35,15 @@ public class PasswordCheckupLauncher {
windowAndroid.getContext().get(), PasswordCheckReferrer.LEAK_DIALOG); windowAndroid.getContext().get(), PasswordCheckReferrer.LEAK_DIALOG);
} }
private static boolean tryLaunchingNativePasswordCheckup(ChromeActivity activity) { @CalledByNative
private static void launchCheckupInAccountWithActivity(String checkupUrl, Activity activity) {
if (tryLaunchingNativePasswordCheckup(activity)) return;
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(checkupUrl));
intent.setPackage(activity.getPackageName());
activity.startActivity(intent);
}
private static boolean tryLaunchingNativePasswordCheckup(Activity activity) {
GooglePasswordManagerUIProvider googlePasswordManagerUIProvider = GooglePasswordManagerUIProvider googlePasswordManagerUIProvider =
AppHooks.get().createGooglePasswordManagerUIProvider(); AppHooks.get().createGooglePasswordManagerUIProvider();
if (googlePasswordManagerUIProvider == null) return false; if (googlePasswordManagerUIProvider == null) return false;
......
...@@ -2845,6 +2845,8 @@ static_library("browser") { ...@@ -2845,6 +2845,8 @@ static_library("browser") {
"password_manager/android/password_accessory_controller_impl.cc", "password_manager/android/password_accessory_controller_impl.cc",
"password_manager/android/password_accessory_controller_impl.h", "password_manager/android/password_accessory_controller_impl.h",
"password_manager/android/password_accessory_metrics_util.h", "password_manager/android/password_accessory_metrics_util.h",
"password_manager/android/password_checkup_launcher_helper.cc",
"password_manager/android/password_checkup_launcher_helper.h",
"password_manager/android/password_generation_controller.h", "password_manager/android/password_generation_controller.h",
"password_manager/android/password_generation_controller_impl.cc", "password_manager/android/password_generation_controller_impl.cc",
"password_manager/android/password_generation_controller_impl.h", "password_manager/android/password_generation_controller_impl.h",
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
package org.chromium.chrome.browser.password_check; package org.chromium.chrome.browser.password_check;
import android.app.Activity;
import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.NativeMethods; import org.chromium.base.annotations.NativeMethods;
import org.chromium.url.GURL; import org.chromium.url.GURL;
...@@ -136,6 +138,13 @@ class PasswordCheckBridge { ...@@ -136,6 +138,13 @@ class PasswordCheckBridge {
mNativePasswordCheckBridge, credentials); mNativePasswordCheckBridge, credentials);
} }
/**
* Launch the password check in the Google Account.
*/
void launchCheckupInAccount(Activity activity) {
PasswordCheckBridgeJni.get().launchCheckupInAccount(mNativePasswordCheckBridge, activity);
}
void updateCredential(CompromisedCredential credential, String newPassword) { void updateCredential(CompromisedCredential credential, String newPassword) {
PasswordCheckBridgeJni.get().updateCredential( PasswordCheckBridgeJni.get().updateCredential(
mNativePasswordCheckBridge, credential, newPassword); mNativePasswordCheckBridge, credential, newPassword);
...@@ -168,6 +177,7 @@ class PasswordCheckBridge { ...@@ -168,6 +177,7 @@ class PasswordCheckBridge {
int getSavedPasswordsCount(long nativePasswordCheckBridge); int getSavedPasswordsCount(long nativePasswordCheckBridge);
void getCompromisedCredentials( void getCompromisedCredentials(
long nativePasswordCheckBridge, CompromisedCredential[] credentials); long nativePasswordCheckBridge, CompromisedCredential[] credentials);
void launchCheckupInAccount(long nativePasswordCheckBridge, Activity activity);
void updateCredential(long nativePasswordCheckBridge, CompromisedCredential credential, void updateCredential(long nativePasswordCheckBridge, CompromisedCredential credential,
String newPassword); String newPassword);
void removeCredential(long nativePasswordCheckBridge, CompromisedCredential credentials); void removeCredential(long nativePasswordCheckBridge, CompromisedCredential credentials);
......
...@@ -73,14 +73,18 @@ class PasswordCheckCoordinator implements PasswordCheckComponentUi, LifecycleObs ...@@ -73,14 +73,18 @@ class PasswordCheckCoordinator implements PasswordCheckComponentUi, LifecycleObs
mReauthenticationHelper); mReauthenticationHelper);
} }
private void launchCheckupInAccount() {
PasswordCheckFactory.getOrCreate().launchCheckupInAccount(mFragmentView.getActivity());
}
@Override @Override
public void onStartFragment() { public void onStartFragment() {
// In the rare case of a restarted activity, don't recreate the model and mediator. // In the rare case of a restarted activity, don't recreate the model and mediator.
if (mModel == null) { if (mModel == null) {
mModel = PasswordCheckProperties.createDefaultModel(); mModel = PasswordCheckProperties.createDefaultModel();
PasswordCheckCoordinator.setUpModelChangeProcessors(mModel, mFragmentView); PasswordCheckCoordinator.setUpModelChangeProcessors(mModel, mFragmentView);
mMediator.initialize( mMediator.initialize(mModel, PasswordCheckFactory.getOrCreate(),
mModel, PasswordCheckFactory.getOrCreate(), mFragmentView.getReferrer()); mFragmentView.getReferrer(), this::launchCheckupInAccount);
} }
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.password_check; package org.chromium.chrome.browser.password_check;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
...@@ -127,6 +128,11 @@ class PasswordCheckImpl implements PasswordCheck, PasswordCheckObserver { ...@@ -127,6 +128,11 @@ class PasswordCheckImpl implements PasswordCheck, PasswordCheckObserver {
return mPasswordCheckBridge.getSavedPasswordsCount(); return mPasswordCheckBridge.getSavedPasswordsCount();
} }
@Override
public void launchCheckupInAccount(Activity activity) {
mPasswordCheckBridge.launchCheckupInAccount(activity);
}
@Override @Override
public void startCheck() { public void startCheck() {
mPasswordCheckBridge.startCheck(); mPasswordCheckBridge.startCheck();
......
...@@ -13,6 +13,7 @@ import static org.chromium.chrome.browser.password_check.PasswordCheckProperties ...@@ -13,6 +13,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.LAUNCH_ACCOUNT_CHECKUP_ACTION;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.RESTART_BUTTON_ACTION; 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;
...@@ -39,6 +40,7 @@ class PasswordCheckMediator ...@@ -39,6 +40,7 @@ class PasswordCheckMediator
private final PasswordCheckChangePasswordHelper mChangePasswordDelegate; private final PasswordCheckChangePasswordHelper mChangePasswordDelegate;
private PropertyModel mModel; private PropertyModel mModel;
private PasswordCheckComponentUi.Delegate mDelegate; private PasswordCheckComponentUi.Delegate mDelegate;
private Runnable mLaunchCheckupInAccount;
PasswordCheckMediator(PasswordCheckChangePasswordHelper changePasswordDelegate, PasswordCheckMediator(PasswordCheckChangePasswordHelper changePasswordDelegate,
PasswordCheckReauthenticationHelper reauthenticationHelper) { PasswordCheckReauthenticationHelper reauthenticationHelper) {
...@@ -47,9 +49,10 @@ class PasswordCheckMediator ...@@ -47,9 +49,10 @@ class PasswordCheckMediator
} }
void initialize(PropertyModel model, PasswordCheckComponentUi.Delegate delegate, void initialize(PropertyModel model, PasswordCheckComponentUi.Delegate delegate,
@PasswordCheckReferrer int passwordCheckReferrer) { @PasswordCheckReferrer int passwordCheckReferrer, Runnable launchCheckupInAccount) {
mModel = model; mModel = model;
mDelegate = delegate; mDelegate = delegate;
mLaunchCheckupInAccount = launchCheckupInAccount;
// If a run is scheduled to happen soon, initialize the UI as running to prevent flickering. // If a run is scheduled to happen soon, initialize the UI as running to prevent flickering.
// Otherwise, initialize the UI with last known state (defaults to IDLE before first run). // Otherwise, initialize the UI with last known state (defaults to IDLE before first run).
...@@ -73,6 +76,7 @@ class PasswordCheckMediator ...@@ -73,6 +76,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(LAUNCH_ACCOUNT_CHECKUP_ACTION, mLaunchCheckupInAccount)
.with(RESTART_BUTTON_ACTION, this::runCheck) .with(RESTART_BUTTON_ACTION, this::runCheck)
.build())); .build()));
} }
...@@ -96,6 +100,7 @@ class PasswordCheckMediator ...@@ -96,6 +100,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(LAUNCH_ACCOUNT_CHECKUP_ACTION, mLaunchCheckupInAccount)
.with(RESTART_BUTTON_ACTION, this::runCheck) .with(RESTART_BUTTON_ACTION, this::runCheck)
.build(); .build();
} else { } else {
......
...@@ -67,11 +67,15 @@ class PasswordCheckProperties { ...@@ -67,11 +67,15 @@ 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> LAUNCH_ACCOUNT_CHECKUP_ACTION =
new PropertyModel.ReadableObjectPropertyKey<>("launch_account_checkup_action");
static final PropertyModel.ReadableObjectPropertyKey<Runnable> RESTART_BUTTON_ACTION = static final PropertyModel.ReadableObjectPropertyKey<Runnable> RESTART_BUTTON_ACTION =
new PropertyModel.WritableObjectPropertyKey<>("restart_button_action"); new PropertyModel.ReadableObjectPropertyKey<>("restart_button_action");
static final PropertyKey[] ALL_KEYS = {CHECK_PROGRESS, CHECK_STATUS, CHECK_TIMESTAMP, static final PropertyKey[] ALL_KEYS = {CHECK_PROGRESS, CHECK_STATUS, CHECK_TIMESTAMP,
COMPROMISED_CREDENTIALS_COUNT, RESTART_BUTTON_ACTION}; COMPROMISED_CREDENTIALS_COUNT, LAUNCH_ACCOUNT_CHECKUP_ACTION,
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);
......
...@@ -13,6 +13,7 @@ import static org.chromium.chrome.browser.password_check.PasswordCheckProperties ...@@ -13,6 +13,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.LAUNCH_ACCOUNT_CHECKUP_ACTION;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.RESTART_BUTTON_ACTION; 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;
...@@ -20,6 +21,7 @@ import static org.chromium.chrome.browser.password_check.PasswordCheckProperties ...@@ -20,6 +21,7 @@ import static org.chromium.chrome.browser.password_check.PasswordCheckProperties
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.text.method.LinkMovementMethod;
import android.util.Pair; import android.util.Pair;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
...@@ -44,6 +46,8 @@ import org.chromium.ui.modelutil.PropertyKey; ...@@ -44,6 +46,8 @@ import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.RecyclerViewAdapter; import org.chromium.ui.modelutil.RecyclerViewAdapter;
import org.chromium.ui.modelutil.SimpleRecyclerViewMcp; import org.chromium.ui.modelutil.SimpleRecyclerViewMcp;
import org.chromium.ui.text.NoUnderlineClickableSpan;
import org.chromium.ui.text.SpanApplier;
import org.chromium.ui.widget.ButtonCompat; import org.chromium.ui.widget.ButtonCompat;
/** /**
...@@ -186,22 +190,30 @@ class PasswordCheckViewBinder { ...@@ -186,22 +190,30 @@ class PasswordCheckViewBinder {
int status = model.get(CHECK_STATUS); int status = model.get(CHECK_STATUS);
Long checkTimestamp = model.get(CHECK_TIMESTAMP); Long checkTimestamp = model.get(CHECK_TIMESTAMP);
Integer compromisedCredentialsCount = model.get(COMPROMISED_CREDENTIALS_COUNT); Integer compromisedCredentialsCount = model.get(COMPROMISED_CREDENTIALS_COUNT);
Runnable launchCheckupInAccount = model.get(LAUNCH_ACCOUNT_CHECKUP_ACTION);
if (key == CHECK_PROGRESS) { if (key == CHECK_PROGRESS) {
updateStatusText(view, status, compromisedCredentialsCount, checkTimestamp, progress); updateStatusText(view, status, compromisedCredentialsCount, checkTimestamp, progress,
launchCheckupInAccount);
} else if (key == CHECK_STATUS) { } else if (key == CHECK_STATUS) {
updateActionButton(view, status, model.get(RESTART_BUTTON_ACTION)); 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,
launchCheckupInAccount);
updateStatusSubtitle(view, status, compromisedCredentialsCount); updateStatusSubtitle(view, status, compromisedCredentialsCount);
} else if (key == CHECK_TIMESTAMP) { } else if (key == CHECK_TIMESTAMP) {
updateStatusText(view, status, compromisedCredentialsCount, checkTimestamp, progress); updateStatusText(view, status, compromisedCredentialsCount, checkTimestamp, progress,
launchCheckupInAccount);
} else if (key == COMPROMISED_CREDENTIALS_COUNT) { } else if (key == COMPROMISED_CREDENTIALS_COUNT) {
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,
launchCheckupInAccount);
updateStatusSubtitle(view, status, compromisedCredentialsCount); updateStatusSubtitle(view, status, compromisedCredentialsCount);
} else if (key == LAUNCH_ACCOUNT_CHECKUP_ACTION) {
assert model.get(LAUNCH_ACCOUNT_CHECKUP_ACTION)
!= null : "Launch checkup in account is always required.";
} else if (key == RESTART_BUTTON_ACTION) { } else if (key == RESTART_BUTTON_ACTION) {
assert model.get(RESTART_BUTTON_ACTION) != null : "Restart action is always required."; assert model.get(RESTART_BUTTON_ACTION) != null : "Restart action is always required.";
} else { } else {
...@@ -268,7 +280,7 @@ class PasswordCheckViewBinder { ...@@ -268,7 +280,7 @@ class PasswordCheckViewBinder {
private static void updateStatusText(View view, @PasswordCheckUIStatus int status, private static void updateStatusText(View view, @PasswordCheckUIStatus int status,
Integer compromisedCredentialsCount, Long checkTimestamp, Integer compromisedCredentialsCount, Long checkTimestamp,
Pair<Integer, Integer> progress) { Pair<Integer, Integer> progress, Runnable launchCheckupInAccount) {
// TODO(crbug.com/1114051): Set default values for header properties. // TODO(crbug.com/1114051): Set default values for header properties.
if (status == PasswordCheckUIStatus.IDLE if (status == PasswordCheckUIStatus.IDLE
&& (compromisedCredentialsCount == null || checkTimestamp == null)) { && (compromisedCredentialsCount == null || checkTimestamp == null)) {
...@@ -277,8 +289,9 @@ class PasswordCheckViewBinder { ...@@ -277,8 +289,9 @@ class PasswordCheckViewBinder {
if (status == PasswordCheckUIStatus.RUNNING && progress == null) return; if (status == PasswordCheckUIStatus.RUNNING && progress == null) return;
TextView statusMessage = view.findViewById(R.id.check_status_message); TextView statusMessage = view.findViewById(R.id.check_status_message);
statusMessage.setText( statusMessage.setText(getStatusMessage(
getStatusMessage(view, status, compromisedCredentialsCount, progress)); view, status, compromisedCredentialsCount, progress, launchCheckupInAccount));
statusMessage.setMovementMethod(LinkMovementMethod.getInstance());
LinearLayout textLayout = view.findViewById(R.id.check_status_text_layout); LinearLayout textLayout = view.findViewById(R.id.check_status_text_layout);
int verticalMargin = getDimensionPixelOffset(view, getStatusTextMargin(status)); int verticalMargin = getDimensionPixelOffset(view, getStatusTextMargin(status));
...@@ -289,14 +302,15 @@ class PasswordCheckViewBinder { ...@@ -289,14 +302,15 @@ class PasswordCheckViewBinder {
statusDescription.setVisibility(getStatusDescriptionVisibility(status)); statusDescription.setVisibility(getStatusDescriptionVisibility(status));
} }
private static String getStatusMessage(View view, @PasswordCheckUIStatus int status, private static CharSequence getStatusMessage(View view, @PasswordCheckUIStatus int status,
Integer compromisedCredentialsCount, Pair<Integer, Integer> progress) { Integer compromisedCredentialsCount, Pair<Integer, Integer> progress,
Runnable launchCheckupInAccount) {
switch (status) { switch (status) {
case PasswordCheckUIStatus.IDLE: case PasswordCheckUIStatus.IDLE:
assert compromisedCredentialsCount != null; assert compromisedCredentialsCount != null;
return compromisedCredentialsCount == 0 return compromisedCredentialsCount == 0
? getString(view, R.string.password_check_status_message_idle_no_leaks) ? getString(view, R.string.password_check_status_message_idle_no_leaks)
: view.getContext().getResources().getQuantityString( : getResources(view).getQuantityString(
R.plurals.password_check_status_message_idle_with_leaks, R.plurals.password_check_status_message_idle_with_leaks,
compromisedCredentialsCount, compromisedCredentialsCount); compromisedCredentialsCount, compromisedCredentialsCount);
case PasswordCheckUIStatus.RUNNING: case PasswordCheckUIStatus.RUNNING:
...@@ -317,8 +331,12 @@ class PasswordCheckViewBinder { ...@@ -317,8 +331,12 @@ class PasswordCheckViewBinder {
case PasswordCheckUIStatus.ERROR_QUOTA_LIMIT: case PasswordCheckUIStatus.ERROR_QUOTA_LIMIT:
return getString(view, R.string.password_check_status_message_error_quota_limit); return getString(view, R.string.password_check_status_message_error_quota_limit);
case PasswordCheckUIStatus.ERROR_QUOTA_LIMIT_ACCOUNT_CHECK: case PasswordCheckUIStatus.ERROR_QUOTA_LIMIT_ACCOUNT_CHECK:
return getString(view, NoUnderlineClickableSpan linkSpan = new NoUnderlineClickableSpan(
R.string.password_check_status_message_error_quota_limit_account_check); getResources(view), unusedView -> launchCheckupInAccount.run());
return SpanApplier.applySpans(
getString(view,
R.string.password_check_status_message_error_quota_limit_account_check),
new SpanApplier.SpanInfo("<link>", "</link>", linkSpan));
case PasswordCheckUIStatus.ERROR_UNKNOWN: case PasswordCheckUIStatus.ERROR_UNKNOWN:
return getString(view, R.string.password_check_status_message_error_unknown); return getString(view, R.string.password_check_status_message_error_unknown);
default: default:
...@@ -348,7 +366,7 @@ class PasswordCheckViewBinder { ...@@ -348,7 +366,7 @@ class PasswordCheckViewBinder {
private static String getStatusDescription(View view, Long checkTimestamp) { private static String getStatusDescription(View view, Long checkTimestamp) {
if (checkTimestamp == null) return null; if (checkTimestamp == null) return null;
Resources res = view.getContext().getResources(); Resources res = getResources(view);
return res.getString(R.string.password_check_status_description_idle, return res.getString(R.string.password_check_status_description_idle,
getTimestamp(res, System.currentTimeMillis() - checkTimestamp)); getTimestamp(res, System.currentTimeMillis() - checkTimestamp));
} }
...@@ -468,11 +486,15 @@ class PasswordCheckViewBinder { ...@@ -468,11 +486,15 @@ class PasswordCheckViewBinder {
} }
private static String getString(View view, int resourceId) { private static String getString(View view, int resourceId) {
return view.getContext().getResources().getString(resourceId); return getResources(view).getString(resourceId);
} }
private static int getDimensionPixelOffset(View view, int resourceId) { private static int getDimensionPixelOffset(View view, int resourceId) {
return view.getContext().getResources().getDimensionPixelOffset(resourceId); return getResources(view).getDimensionPixelOffset(resourceId);
}
private static Resources getResources(View view) {
return view.getContext().getResources();
} }
private static void setTintListForCompoundDrawables( private static void setTintListForCompoundDrawables(
......
...@@ -203,7 +203,7 @@ ...@@ -203,7 +203,7 @@
Chrome couldn't check all passwords. Try again tomorrow. Chrome couldn't check all passwords. Try again tomorrow.
</message> </message>
<message name="IDS_PASSWORD_CHECK_STATUS_MESSAGE_ERROR_QUOTA_LIMIT_ACCOUNT_CHECK" desc="Error message explaining that the password check failed because the user has exceeded their quota and redirecting to check in the Google Account."> <message name="IDS_PASSWORD_CHECK_STATUS_MESSAGE_ERROR_QUOTA_LIMIT_ACCOUNT_CHECK" desc="Error message explaining that the password check failed because the user has exceeded their quota and redirecting to check in the Google Account.">
Chrome couldn't check all passwords. Try again tomorrow or check passwords in your Google Account. Chrome couldn't check all passwords. Try again tomorrow or <ph name="BEGIN_LINK">&lt;link&gt;</ph>check passwords in your Google Account<ph name="END_LINK">&lt;/link&gt;</ph>.
</message> </message>
<message name="IDS_PASSWORD_CHECK_STATUS_MESSAGE_ERROR_SIGNED_OUT" desc="Error message explaining that the password check failed because the user is signed-out."> <message name="IDS_PASSWORD_CHECK_STATUS_MESSAGE_ERROR_SIGNED_OUT" desc="Error message explaining that the password check failed because the user is signed-out.">
Chrome can check your passwords when you sign in with your Google Account. Chrome can check your passwords when you sign in with your Google Account.
......
d7b9987fb0a45cf5f829ba2750b0d9dcb8564a60 c4546cf199aa6314ead807fa1fc0e1ed8b779a83
\ No newline at end of file \ No newline at end of file
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.password_check; package org.chromium.chrome.browser.password_check;
import android.app.Activity;
import android.content.Context; import android.content.Context;
/** /**
...@@ -104,6 +105,11 @@ public interface PasswordCheck extends PasswordCheckComponentUi.Delegate { ...@@ -104,6 +105,11 @@ public interface PasswordCheck extends PasswordCheckComponentUi.Delegate {
*/ */
int getSavedPasswordsCount(); int getSavedPasswordsCount();
/**
* Launch the password check in the Google Account.
*/
void launchCheckupInAccount(Activity activity);
/** /**
* Starts the password check, if one is not running already. * Starts the password check, if one is not running already.
*/ */
......
...@@ -28,6 +28,7 @@ import static org.chromium.chrome.browser.password_check.PasswordCheckProperties ...@@ -28,6 +28,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.LAUNCH_ACCOUNT_CHECKUP_ACTION;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.RESTART_BUTTON_ACTION; 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;
...@@ -123,6 +124,8 @@ public class PasswordCheckViewTest { ...@@ -123,6 +124,8 @@ public class PasswordCheckViewTest {
@Mock @Mock
private PasswordCheckCoordinator.CredentialEventHandler mMockHandler; private PasswordCheckCoordinator.CredentialEventHandler mMockHandler;
@Mock @Mock
private Runnable mMockLaunchCheckupInAccount;
@Mock
private Runnable mMockStartButtonCallback; private Runnable mMockStartButtonCallback;
@Rule @Rule
...@@ -253,11 +256,11 @@ public class PasswordCheckViewTest { ...@@ -253,11 +256,11 @@ public class PasswordCheckViewTest {
@Test @Test
@MediumTest @MediumTest
public void testStatusRunnningText() { public void testStatusRunningText() {
runOnUiThreadBlocking( runOnUiThreadBlocking(
() -> { mModel.get(ITEMS).add(buildHeader(RUNNING, UNKNOWN_PROGRESS)); }); () -> { mModel.get(ITEMS).add(buildHeader(RUNNING, UNKNOWN_PROGRESS)); });
waitForListViewToHaveLength(1); waitForListViewToHaveLength(1);
assertThat(getHeaderMessage().getText(), assertThat(getHeaderMessageText(),
is(getString(R.string.password_check_status_message_initial_running))); is(getString(R.string.password_check_status_message_initial_running)));
assertThat(getHeaderMessage().getVisibility(), is(View.VISIBLE)); assertThat(getHeaderMessage().getVisibility(), is(View.VISIBLE));
assertThat(getHeaderDescription().getVisibility(), is(View.GONE)); assertThat(getHeaderDescription().getVisibility(), is(View.GONE));
...@@ -270,7 +273,7 @@ public class PasswordCheckViewTest { ...@@ -270,7 +273,7 @@ public class PasswordCheckViewTest {
runOnUiThreadBlocking( runOnUiThreadBlocking(
() -> { mModel.get(ITEMS).add(buildHeader(IDLE, 0, checkTimestamp)); }); () -> { mModel.get(ITEMS).add(buildHeader(IDLE, 0, checkTimestamp)); });
waitForListViewToHaveLength(1); waitForListViewToHaveLength(1);
assertThat(getHeaderMessage().getText(), assertThat(getHeaderMessageText(),
is(getString(R.string.password_check_status_message_idle_no_leaks))); is(getString(R.string.password_check_status_message_idle_no_leaks)));
assertThat(getHeaderMessage().getVisibility(), is(View.VISIBLE)); assertThat(getHeaderMessage().getVisibility(), is(View.VISIBLE));
assertThat(getHeaderDescription().getVisibility(), is(View.VISIBLE)); assertThat(getHeaderDescription().getVisibility(), is(View.VISIBLE));
...@@ -283,7 +286,7 @@ public class PasswordCheckViewTest { ...@@ -283,7 +286,7 @@ public class PasswordCheckViewTest {
runOnUiThreadBlocking( runOnUiThreadBlocking(
() -> { mModel.get(ITEMS).add(buildHeader(IDLE, LEAKS_COUNT, checkTimestamp)); }); () -> { mModel.get(ITEMS).add(buildHeader(IDLE, LEAKS_COUNT, checkTimestamp)); });
waitForListViewToHaveLength(1); waitForListViewToHaveLength(1);
assertThat(getHeaderMessage().getText(), assertThat(getHeaderMessageText(),
is(mPasswordCheckView.getContext().getResources().getQuantityString( is(mPasswordCheckView.getContext().getResources().getQuantityString(
R.plurals.password_check_status_message_idle_with_leaks, LEAKS_COUNT, R.plurals.password_check_status_message_idle_with_leaks, LEAKS_COUNT,
LEAKS_COUNT))); LEAKS_COUNT)));
...@@ -296,7 +299,7 @@ public class PasswordCheckViewTest { ...@@ -296,7 +299,7 @@ public class PasswordCheckViewTest {
public void testStatusErrorOfflineText() { public void testStatusErrorOfflineText() {
runOnUiThreadBlocking(() -> { mModel.get(ITEMS).add(buildHeader(ERROR_OFFLINE)); }); runOnUiThreadBlocking(() -> { mModel.get(ITEMS).add(buildHeader(ERROR_OFFLINE)); });
waitForListViewToHaveLength(1); waitForListViewToHaveLength(1);
assertThat(getHeaderMessage().getText(), assertThat(getHeaderMessageText(),
is(getString(R.string.password_check_status_message_error_offline))); is(getString(R.string.password_check_status_message_error_offline)));
assertThat(getHeaderMessage().getVisibility(), is(View.VISIBLE)); assertThat(getHeaderMessage().getVisibility(), is(View.VISIBLE));
assertThat(getHeaderDescription().getVisibility(), is(View.GONE)); assertThat(getHeaderDescription().getVisibility(), is(View.GONE));
...@@ -307,7 +310,7 @@ public class PasswordCheckViewTest { ...@@ -307,7 +310,7 @@ public class PasswordCheckViewTest {
public void testStatusErrorNoPasswordsText() { public void testStatusErrorNoPasswordsText() {
runOnUiThreadBlocking(() -> { mModel.get(ITEMS).add(buildHeader(ERROR_NO_PASSWORDS)); }); runOnUiThreadBlocking(() -> { mModel.get(ITEMS).add(buildHeader(ERROR_NO_PASSWORDS)); });
waitForListViewToHaveLength(1); waitForListViewToHaveLength(1);
assertThat(getHeaderMessage().getText(), assertThat(getHeaderMessageText(),
is(getString(R.string.password_check_status_message_error_no_passwords))); is(getString(R.string.password_check_status_message_error_no_passwords)));
assertThat(getHeaderMessage().getVisibility(), is(View.VISIBLE)); assertThat(getHeaderMessage().getVisibility(), is(View.VISIBLE));
assertThat(getHeaderDescription().getVisibility(), is(View.GONE)); assertThat(getHeaderDescription().getVisibility(), is(View.GONE));
...@@ -318,7 +321,7 @@ public class PasswordCheckViewTest { ...@@ -318,7 +321,7 @@ public class PasswordCheckViewTest {
public void testStatusErrorQuotaLimitText() { public void testStatusErrorQuotaLimitText() {
runOnUiThreadBlocking(() -> { mModel.get(ITEMS).add(buildHeader(ERROR_QUOTA_LIMIT)); }); runOnUiThreadBlocking(() -> { mModel.get(ITEMS).add(buildHeader(ERROR_QUOTA_LIMIT)); });
waitForListViewToHaveLength(1); waitForListViewToHaveLength(1);
assertThat(getHeaderMessage().getText(), assertThat(getHeaderMessageText(),
is(getString(R.string.password_check_status_message_error_quota_limit))); is(getString(R.string.password_check_status_message_error_quota_limit)));
assertThat(getHeaderMessage().getVisibility(), is(View.VISIBLE)); assertThat(getHeaderMessage().getVisibility(), is(View.VISIBLE));
assertThat(getHeaderDescription().getVisibility(), is(View.GONE)); assertThat(getHeaderDescription().getVisibility(), is(View.GONE));
...@@ -330,11 +333,14 @@ public class PasswordCheckViewTest { ...@@ -330,11 +333,14 @@ public class PasswordCheckViewTest {
runOnUiThreadBlocking( runOnUiThreadBlocking(
() -> { mModel.get(ITEMS).add(buildHeader(ERROR_QUOTA_LIMIT_ACCOUNT_CHECK)); }); () -> { mModel.get(ITEMS).add(buildHeader(ERROR_QUOTA_LIMIT_ACCOUNT_CHECK)); });
waitForListViewToHaveLength(1); waitForListViewToHaveLength(1);
assertThat(getHeaderMessage().getText(), assertThat(getHeaderMessageText(),
is(getString( is(getString(R.string.password_check_status_message_error_quota_limit_account_check)
R.string.password_check_status_message_error_quota_limit_account_check))); .replace("<link>", "")
.replace("</link>", "")));
assertThat(getHeaderMessage().getVisibility(), is(View.VISIBLE)); assertThat(getHeaderMessage().getVisibility(), is(View.VISIBLE));
assertThat(getHeaderDescription().getVisibility(), is(View.GONE)); assertThat(getHeaderDescription().getVisibility(), is(View.GONE));
TouchCommon.singleClickView(getHeaderMessage());
waitForEvent(mMockLaunchCheckupInAccount).run();
} }
@Test @Test
...@@ -342,7 +348,7 @@ public class PasswordCheckViewTest { ...@@ -342,7 +348,7 @@ public class PasswordCheckViewTest {
public void testStatusErrorSignedOutText() { public void testStatusErrorSignedOutText() {
runOnUiThreadBlocking(() -> { mModel.get(ITEMS).add(buildHeader(ERROR_SIGNED_OUT)); }); runOnUiThreadBlocking(() -> { mModel.get(ITEMS).add(buildHeader(ERROR_SIGNED_OUT)); });
waitForListViewToHaveLength(1); waitForListViewToHaveLength(1);
assertThat(getHeaderMessage().getText(), assertThat(getHeaderMessageText(),
is(getString(R.string.password_check_status_message_error_signed_out))); is(getString(R.string.password_check_status_message_error_signed_out)));
assertThat(getHeaderMessage().getVisibility(), is(View.VISIBLE)); assertThat(getHeaderMessage().getVisibility(), is(View.VISIBLE));
assertThat(getHeaderDescription().getVisibility(), is(View.GONE)); assertThat(getHeaderDescription().getVisibility(), is(View.GONE));
...@@ -353,7 +359,7 @@ public class PasswordCheckViewTest { ...@@ -353,7 +359,7 @@ public class PasswordCheckViewTest {
public void testStatusErrorUnknownText() { public void testStatusErrorUnknownText() {
runOnUiThreadBlocking(() -> { mModel.get(ITEMS).add(buildHeader(ERROR_UNKNOWN)); }); runOnUiThreadBlocking(() -> { mModel.get(ITEMS).add(buildHeader(ERROR_UNKNOWN)); });
waitForListViewToHaveLength(1); waitForListViewToHaveLength(1);
assertThat(getHeaderMessage().getText(), assertThat(getHeaderMessageText(),
is(getString(R.string.password_check_status_message_error_unknown))); is(getString(R.string.password_check_status_message_error_unknown)));
assertThat(getHeaderMessage().getVisibility(), is(View.VISIBLE)); assertThat(getHeaderMessage().getVisibility(), is(View.VISIBLE));
assertThat(getHeaderDescription().getVisibility(), is(View.GONE)); assertThat(getHeaderDescription().getVisibility(), is(View.GONE));
...@@ -588,6 +594,7 @@ public class PasswordCheckViewTest { ...@@ -588,6 +594,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(LAUNCH_ACCOUNT_CHECKUP_ACTION, mMockLaunchCheckupInAccount)
.with(RESTART_BUTTON_ACTION, mMockStartButtonCallback) .with(RESTART_BUTTON_ACTION, mMockStartButtonCallback)
.build()); .build());
} }
...@@ -660,6 +667,10 @@ public class PasswordCheckViewTest { ...@@ -660,6 +667,10 @@ public class PasswordCheckViewTest {
return getStatus().findViewById(R.id.check_status_message); return getStatus().findViewById(R.id.check_status_message);
} }
private String getHeaderMessageText() {
return getHeaderMessage().getText().toString();
}
private TextView getHeaderSubtitle() { private TextView getHeaderSubtitle() {
return getStatus().findViewById(R.id.check_status_subtitle); return getStatus().findViewById(R.id.check_status_subtitle);
} }
......
...@@ -28,6 +28,7 @@ import static org.chromium.chrome.browser.password_check.PasswordCheckProperties ...@@ -28,6 +28,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.LAUNCH_ACCOUNT_CHECKUP_ACTION;
import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.RESTART_BUTTON_ACTION; 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;
...@@ -100,7 +101,7 @@ public class PasswordCheckControllerTest { ...@@ -100,7 +101,7 @@ public class PasswordCheckControllerTest {
mModel = PasswordCheckProperties.createDefaultModel(); mModel = PasswordCheckProperties.createDefaultModel();
mMediator = new PasswordCheckMediator(mChangePasswordDelegate, mReauthenticationHelper); mMediator = new PasswordCheckMediator(mChangePasswordDelegate, mReauthenticationHelper);
PasswordCheckFactory.setPasswordCheckForTesting(mPasswordCheck); PasswordCheckFactory.setPasswordCheckForTesting(mPasswordCheck);
mMediator.initialize(mModel, mDelegate, PasswordCheckReferrer.PASSWORD_SETTINGS); mMediator.initialize(mModel, mDelegate, PasswordCheckReferrer.PASSWORD_SETTINGS, () -> {});
} }
@Test @Test
...@@ -125,7 +126,7 @@ public class PasswordCheckControllerTest { ...@@ -125,7 +126,7 @@ public class PasswordCheckControllerTest {
public void testInitializeHeaderWithLastStatusWhenComingFromSafetyCheck() { public void testInitializeHeaderWithLastStatusWhenComingFromSafetyCheck() {
clearInvocations(mPasswordCheck); // Clear invocations from setup code. clearInvocations(mPasswordCheck); // Clear invocations from setup code.
when(mPasswordCheck.getCheckStatus()).thenReturn(PasswordCheckUIStatus.IDLE); when(mPasswordCheck.getCheckStatus()).thenReturn(PasswordCheckUIStatus.IDLE);
mMediator.initialize(mModel, mDelegate, PasswordCheckReferrer.SAFETY_CHECK); mMediator.initialize(mModel, mDelegate, PasswordCheckReferrer.SAFETY_CHECK, () -> {});
assertIdleHeader(mModel.get(ITEMS).get(0)); assertIdleHeader(mModel.get(ITEMS).get(0));
verify(mPasswordCheck, never()).startCheck(); verify(mPasswordCheck, never()).startCheck();
} }
...@@ -300,7 +301,6 @@ public class PasswordCheckControllerTest { ...@@ -300,7 +301,6 @@ 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(
...@@ -309,7 +309,6 @@ public class PasswordCheckControllerTest { ...@@ -309,7 +309,6 @@ 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(
...@@ -317,5 +316,6 @@ public class PasswordCheckControllerTest { ...@@ -317,5 +316,6 @@ public class PasswordCheckControllerTest {
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)); assertNotNull(header.model.get(RESTART_BUTTON_ACTION));
assertNotNull(header.model.get(LAUNCH_ACCOUNT_CHECKUP_ACTION));
} }
} }
...@@ -9,7 +9,9 @@ ...@@ -9,7 +9,9 @@
#include "base/android/jni_string.h" #include "base/android/jni_string.h"
#include "chrome/browser/password_check/android/jni_headers/CompromisedCredential_jni.h" #include "chrome/browser/password_check/android/jni_headers/CompromisedCredential_jni.h"
#include "chrome/browser/password_check/android/jni_headers/PasswordCheckBridge_jni.h" #include "chrome/browser/password_check/android/jni_headers/PasswordCheckBridge_jni.h"
#include "chrome/browser/password_manager/android/password_checkup_launcher_helper.h"
#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_manager.h"
#include "components/password_manager/core/browser/password_manager_util.h"
#include "components/password_manager/core/browser/ui/compromised_credentials_manager.h" #include "components/password_manager/core/browser/ui/compromised_credentials_manager.h"
#include "url/android/gurl_android.h" #include "url/android/gurl_android.h"
...@@ -89,6 +91,16 @@ void PasswordCheckBridge::GetCompromisedCredentials( ...@@ -89,6 +91,16 @@ void PasswordCheckBridge::GetCompromisedCredentials(
} }
} }
void PasswordCheckBridge::LaunchCheckupInAccount(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& activity) {
PasswordCheckupLauncherHelper::LaunchCheckupInAccountWithActivity(
env,
base::android::ConvertUTF8ToJavaString(
env, password_manager::GetPasswordCheckupURL().spec()),
activity);
}
void PasswordCheckBridge::UpdateCredential( void PasswordCheckBridge::UpdateCredential(
JNIEnv* env, JNIEnv* env,
const base::android::JavaParamRef<jobject>& credential, const base::android::JavaParamRef<jobject>& credential,
......
...@@ -42,6 +42,11 @@ class PasswordCheckBridge : public PasswordCheckManager::Observer { ...@@ -42,6 +42,11 @@ class PasswordCheckBridge : public PasswordCheckManager::Observer {
JNIEnv* env, JNIEnv* env,
const base::android::JavaParamRef<jobjectArray>& credentials); const base::android::JavaParamRef<jobjectArray>& credentials);
// Called by Java to launch a password check from the Google Account.
void LaunchCheckupInAccount(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& activity);
// Called by Java to update a single compromised credential in the password // Called by Java to update a single compromised credential in the password
// store. // store.
void UpdateCredential( void UpdateCredential(
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include "base/android/jni_string.h" #include "base/android/jni_string.h"
#include "base/feature_list.h" #include "base/feature_list.h"
#include "chrome/android/chrome_jni_headers/PasswordChangeLauncher_jni.h" #include "chrome/android/chrome_jni_headers/PasswordChangeLauncher_jni.h"
#include "chrome/android/chrome_jni_headers/PasswordCheckupLauncher_jni.h" #include "chrome/browser/password_manager/android/password_checkup_launcher_helper.h"
#include "chrome/browser/ui/android/passwords/credential_leak_dialog_view_android.h" #include "chrome/browser/ui/android/passwords/credential_leak_dialog_view_android.h"
#include "chrome/common/url_constants.h" #include "chrome/common/url_constants.h"
#include "components/password_manager/core/browser/leak_detection_dialog_utils.h" #include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
...@@ -61,10 +61,10 @@ void CredentialLeakControllerAndroid::OnAcceptDialog() { ...@@ -61,10 +61,10 @@ void CredentialLeakControllerAndroid::OnAcceptDialog() {
if (ShouldCheckPasswords()) { if (ShouldCheckPasswords()) {
if (base::FeatureList::IsEnabled( if (base::FeatureList::IsEnabled(
password_manager::features::kPasswordCheck)) { password_manager::features::kPasswordCheck)) {
Java_PasswordCheckupLauncher_launchLocalCheckup( PasswordCheckupLauncherHelper::LaunchLocalCheckup(
env, window_android_->GetJavaObject()); env, window_android_->GetJavaObject());
} else { } else {
Java_PasswordCheckupLauncher_launchCheckupInAccount( PasswordCheckupLauncherHelper::LaunchCheckupInAccountWithWindowAndroid(
env, env,
base::android::ConvertUTF8ToJavaString( base::android::ConvertUTF8ToJavaString(
env, password_manager::GetPasswordCheckupURL().spec()), env, password_manager::GetPasswordCheckupURL().spec()),
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/password_manager/android/password_checkup_launcher_helper.h"
#include "chrome/android/chrome_jni_headers/PasswordCheckupLauncher_jni.h"
// static
void PasswordCheckupLauncherHelper::LaunchCheckupInAccountWithWindowAndroid(
JNIEnv* env,
const base::android::JavaRef<jstring>& checkupUrl,
const base::android::JavaRef<jobject>& windowAndroid) {
Java_PasswordCheckupLauncher_launchCheckupInAccountWithWindowAndroid(
env, checkupUrl, windowAndroid);
}
// static
void PasswordCheckupLauncherHelper::LaunchLocalCheckup(
JNIEnv* env,
const base::android::JavaRef<jobject>& windowAndroid) {
Java_PasswordCheckupLauncher_launchLocalCheckup(env, windowAndroid);
}
// static
void PasswordCheckupLauncherHelper::LaunchCheckupInAccountWithActivity(
JNIEnv* env,
const base::android::JavaRef<jstring>& checkupUrl,
const base::android::JavaRef<jobject>& activity) {
Java_PasswordCheckupLauncher_launchCheckupInAccountWithActivity(
env, checkupUrl, activity);
}
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_PASSWORD_MANAGER_ANDROID_PASSWORD_CHECKUP_LAUNCHER_HELPER_H_
#define CHROME_BROWSER_PASSWORD_MANAGER_ANDROID_PASSWORD_CHECKUP_LAUNCHER_HELPER_H_
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
// Helper class used to access the methods of the java class
// PasswordCheckupLauncher from multiple native side locations
class PasswordCheckupLauncherHelper {
public:
// Launch the bulk password check in the Google Account
static void LaunchCheckupInAccountWithWindowAndroid(
JNIEnv* env,
const base::android::JavaRef<jstring>& checkupUrl,
const base::android::JavaRef<jobject>& windowAndroid);
// Launch the bulk password check locally
static void LaunchLocalCheckup(
JNIEnv* env,
const base::android::JavaRef<jobject>& windowAndroid);
// Launch the bulk password check in the Google Account using an activity
// rather than a WindowAndroid
static void LaunchCheckupInAccountWithActivity(
JNIEnv* env,
const base::android::JavaRef<jstring>& checkupUrl,
const base::android::JavaRef<jobject>& activity);
};
#endif // CHROME_BROWSER_PASSWORD_MANAGER_ANDROID_PASSWORD_CHECKUP_LAUNCHER_HELPER_H_
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