Commit b12a3803 authored by Andrey Zaytsev's avatar Andrey Zaytsev Committed by Commit Bot

Safety check on Android: integrated with the password check

* Removed bulk_leak_check_controller_android classes, as they were part of the temporary API for the password check and never actually got used
* Used an instance of the PasswordCheck class to manage the lifecycle of the password check in Safety check
* Changed the initialization logic to account for the asynchronous availability of the # of saved and compromised passwords
* Added logic to block displaying successful states without compromises on fetching the data from disk (# of saved and compromised passwords)
* Added unit tests to verify various asynchronous timing scenarios

Bug: 1070620
Change-Id: Ia4aee1b06ba820f551a4f66c923174d20b5f8007
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2336078Reviewed-by: default avatarNatalie Chouinard <chouinard@chromium.org>
Reviewed-by: default avatarFriedrich [CET] <fhorschig@chromium.org>
Commit-Queue: Andrey Zaytsev <andzaytsev@google.com>
Cr-Commit-Position: refs/heads/master@{#795836}
parent 271ae1de
...@@ -2925,7 +2925,6 @@ static_library("browser") { ...@@ -2925,7 +2925,6 @@ static_library("browser") {
"//chrome/browser/notifications/scheduler/public", "//chrome/browser/notifications/scheduler/public",
"//chrome/browser/offline_pages/prefetch/notifications", "//chrome/browser/offline_pages/prefetch/notifications",
"//chrome/browser/optimization_guide/android:jni_headers", "//chrome/browser/optimization_guide/android:jni_headers",
"//chrome/browser/password_check/android",
"//chrome/browser/password_check/android/internal:jni_headers", "//chrome/browser/password_check/android/internal:jni_headers",
"//chrome/browser/payments/android:jni_headers", "//chrome/browser/payments/android:jni_headers",
"//chrome/browser/policy/android:jni_headers", "//chrome/browser/policy/android:jni_headers",
......
...@@ -4,14 +4,6 @@ ...@@ -4,14 +4,6 @@
import("//build/config/android/rules.gni") import("//build/config/android/rules.gni")
source_set("android") {
sources = [
"bulk_leak_check_controller_android.cc",
"bulk_leak_check_controller_android.h",
]
deps = [ "//components/password_manager/core/browser" ]
}
java_cpp_enum("password_check_enums_srcjar") { java_cpp_enum("password_check_enums_srcjar") {
sources = [ "password_check_ui_status.h" ] sources = [ "password_check_ui_status.h" ]
} }
...@@ -25,12 +17,8 @@ android_library("password_check_java_enums") { ...@@ -25,12 +17,8 @@ android_library("password_check_java_enums") {
source_set("unit_tests") { source_set("unit_tests") {
testonly = true testonly = true
sources = [ sources = [ "password_check_manager_unittest.cc" ]
"bulk_leak_check_controller_android_unittest.cc",
"password_check_manager_unittest.cc",
]
deps = [ deps = [
":android",
":password_check_enums_srcjar", ":password_check_enums_srcjar",
"//base/test:test_support", "//base/test:test_support",
"//chrome/browser", "//chrome/browser",
......
// 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_check/android/bulk_leak_check_controller_android.h"
BulkLeakCheckControllerAndroid::BulkLeakCheckControllerAndroid() = default;
BulkLeakCheckControllerAndroid::~BulkLeakCheckControllerAndroid() = default;
void BulkLeakCheckControllerAndroid::AddObserver(Observer* obs) {
observers_.AddObserver(obs);
}
void BulkLeakCheckControllerAndroid::RemoveObserver(Observer* obs) {
observers_.RemoveObserver(obs);
}
void BulkLeakCheckControllerAndroid::StartPasswordCheck() {
// TODO(crbug.com/1092444): connect with the actual passwords check logic.
for (Observer& obs : observers_) {
obs.OnStateChanged(password_manager::BulkLeakCheckService::State::kIdle);
}
}
int BulkLeakCheckControllerAndroid::GetNumberOfSavedPasswords() {
// TODO(crbug.com/1092444): connect with the actual passwords check logic.
return 0;
}
int BulkLeakCheckControllerAndroid::GetNumberOfLeaksFromLastCheck() {
// TODO(crbug.com/1092444): connect with the actual passwords check logic.
return 0;
}
// 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_CHECK_ANDROID_BULK_LEAK_CHECK_CONTROLLER_ANDROID_H_
#define CHROME_BROWSER_PASSWORD_CHECK_ANDROID_BULK_LEAK_CHECK_CONTROLLER_ANDROID_H_
#include "base/observer_list.h"
#include "components/password_manager/core/browser/bulk_leak_check_service.h"
// This controller allows Android code to interact with the bulk credential leak
// check. Supported interactions include starting the password check, as well as
// getting notified when the state is changed and when each credential is
// checked.
class BulkLeakCheckControllerAndroid {
public:
class Observer : public base::CheckedObserver {
public:
using DoneCount = util::StrongAlias<class DoneCountTag, int>;
using TotalCount = util::StrongAlias<class TotalCountTag, int>;
// Invoked on every observer whenever the state of the bulk leak check
// changes.
virtual void OnStateChanged(
password_manager::BulkLeakCheckService::State state) = 0;
// Invoked on every observer whenever a new credential is successfully
// checked.
virtual void OnCredentialDone(
const password_manager::LeakCheckCredential& credential,
password_manager::IsLeaked is_leaked,
DoneCount credentials_checked,
TotalCount total_to_check) = 0;
};
BulkLeakCheckControllerAndroid();
~BulkLeakCheckControllerAndroid();
void AddObserver(Observer* obs);
void RemoveObserver(Observer* obs);
// Starts the bulk passwords check using all the saved credentials in the
// user's password store.
void StartPasswordCheck();
// Returns the total number of passwords saved by the user.
int GetNumberOfSavedPasswords();
// Returns the last known number of leaked password as of the latest check.
// Does not affect the state of the bulk leak check.
int GetNumberOfLeaksFromLastCheck();
private:
base::ObserverList<Observer> observers_;
};
#endif // CHROME_BROWSER_PASSWORD_CHECK_ANDROID_BULK_LEAK_CHECK_CONTROLLER_ANDROID_H_
// 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_check/android/bulk_leak_check_controller_android.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using password_manager::BulkLeakCheckService;
using password_manager::IsLeaked;
using password_manager::LeakCheckCredential;
using ::testing::AtLeast;
using ::testing::NiceMock;
namespace {
class MockObserver : public BulkLeakCheckControllerAndroid::Observer {
public:
MOCK_METHOD(void,
OnStateChanged,
(BulkLeakCheckService::State state),
(override));
MOCK_METHOD(void,
OnCredentialDone,
(const LeakCheckCredential& credential,
IsLeaked is_leaked,
DoneCount credentials_checked,
TotalCount total_to_check),
(override));
};
} // namespace
class BulkLeakCheckControllerAndroidTest : public testing::Test {
public:
BulkLeakCheckControllerAndroidTest() { controller_.AddObserver(&observer_); }
protected:
BulkLeakCheckControllerAndroid controller_;
NiceMock<MockObserver> observer_;
};
TEST_F(BulkLeakCheckControllerAndroidTest, StartPasswordCheck) {
EXPECT_CALL(observer_, OnStateChanged(BulkLeakCheckService::State::kIdle))
.Times(1);
controller_.StartPasswordCheck();
}
TEST_F(BulkLeakCheckControllerAndroidTest, GetNumberOfSavedPasswords) {
EXPECT_EQ(0, controller_.GetNumberOfSavedPasswords());
}
TEST_F(BulkLeakCheckControllerAndroidTest, GetNumberOfLeaksFromLastCheck) {
EXPECT_EQ(0, controller_.GetNumberOfLeaksFromLastCheck());
}
...@@ -48,7 +48,11 @@ public class PasswordCheckFactory { ...@@ -48,7 +48,11 @@ public class PasswordCheckFactory {
sPasswordCheck = passwordCheck; sPasswordCheck = passwordCheck;
} }
@VisibleForTesting /**
* Returns the underlying instance.
* Should only be used when there's a need to avoid creating a new instance.
* @return A {@link PasswordCheeck} instance as stored here.
*/
public static PasswordCheck getPasswordCheckInstance() { public static PasswordCheck getPasswordCheckInstance() {
return sPasswordCheck; return sPasswordCheck;
} }
......
...@@ -56,7 +56,7 @@ public interface PasswordCheck extends PasswordCheckComponentUi.Delegate { ...@@ -56,7 +56,7 @@ public interface PasswordCheck extends PasswordCheckComponentUi.Delegate {
void destroy(); void destroy();
/** /**
* Adds a new observer to the list of observers * Adds a new observer to the list of observers. If it's already there, does nothing.
* @param obs An {@link Observer} implementation instance. * @param obs An {@link Observer} implementation instance.
* @param callImmediatelyIfReady Invokes {@link Observer#onCompromisedCredentialsFetchCompleted} * @param callImmediatelyIfReady Invokes {@link Observer#onCompromisedCredentialsFetchCompleted}
* and {@link Observer#onSavedPasswordsFetchCompleted} on the observer if the corresponding * and {@link Observer#onSavedPasswordsFetchCompleted} on the observer if the corresponding
...@@ -65,7 +65,7 @@ public interface PasswordCheck extends PasswordCheckComponentUi.Delegate { ...@@ -65,7 +65,7 @@ public interface PasswordCheck extends PasswordCheckComponentUi.Delegate {
void addObserver(Observer obs, boolean callImmediatelyIfReady); void addObserver(Observer obs, boolean callImmediatelyIfReady);
/** /**
* Removes a given observer from the observers list if it is there. * Removes a given observer from the observers list if it is there. Otherwise, does nothing.
* @param obs An {@link Observer} implementation instance. * @param obs An {@link Observer} implementation instance.
*/ */
void removeObserver(Observer obs); void removeObserver(Observer obs);
...@@ -96,7 +96,7 @@ public interface PasswordCheck extends PasswordCheckComponentUi.Delegate { ...@@ -96,7 +96,7 @@ public interface PasswordCheck extends PasswordCheckComponentUi.Delegate {
void startCheck(); void startCheck();
/** /**
* Stops the password check, if one is running. * Stops the password check, if one is running. Otherwise, does nothing.
*/ */
void stopCheck(); void stopCheck();
} }
...@@ -38,6 +38,8 @@ android_library("java") { ...@@ -38,6 +38,8 @@ android_library("java") {
"//base:base_java", "//base:base_java",
"//base:jni_java", "//base:jni_java",
"//chrome/browser/flags:java", "//chrome/browser/flags:java",
"//chrome/browser/password_check:public_java",
"//chrome/browser/password_check/android:password_check_java_enums",
"//chrome/browser/password_manager/android:java", "//chrome/browser/password_manager/android:java",
"//chrome/browser/preferences:java", "//chrome/browser/preferences:java",
"//chrome/browser/safe_browsing/android:java", "//chrome/browser/safe_browsing/android:java",
...@@ -70,6 +72,8 @@ android_library("javatests") { ...@@ -70,6 +72,8 @@ android_library("javatests") {
"//base:base_java", "//base:base_java",
"//base:base_java_test_support", "//base:base_java_test_support",
"//base/test:test_support_java", "//base/test:test_support_java",
"//chrome/browser/flags:java",
"//chrome/browser/password_check:public_java",
"//chrome/browser/preferences:java", "//chrome/browser/preferences:java",
"//chrome/browser/settings:test_support_java", "//chrome/browser/settings:test_support_java",
"//chrome/test/android:chrome_java_test_support", "//chrome/test/android:chrome_java_test_support",
...@@ -97,8 +101,15 @@ android_library("junit") { ...@@ -97,8 +101,15 @@ android_library("junit") {
"//base:base_java_test_support", "//base:base_java_test_support",
"//base:base_junit_test_support", "//base:base_junit_test_support",
"//base/test:test_support_java", "//base/test:test_support_java",
"//chrome/browser/flags:java",
"//chrome/browser/password_check:public_java",
"//chrome/browser/password_check/android:password_check_java_enums",
# Robolectric needs the full PasswordCheckFactory implementation.
"//chrome/browser/password_check/android/internal:internal_factory_java",
"//chrome/browser/preferences:java", "//chrome/browser/preferences:java",
"//chrome/browser/settings:java", "//chrome/browser/settings:java",
"//chrome/test/android:chrome_java_test_support",
"//third_party/junit:junit", "//third_party/junit:junit",
"//third_party/mockito:mockito_java", "//third_party/mockito:mockito_java",
"//ui/android:ui_full_java", "//ui/android:ui_full_java",
......
...@@ -6,7 +6,6 @@ package org.chromium.chrome.browser.safety_check; ...@@ -6,7 +6,6 @@ package org.chromium.chrome.browser.safety_check;
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.chrome.browser.password_check.BulkLeakCheckServiceState;
/** /**
* Provides access to the C++ multi-platform Safety check code in * Provides access to the C++ multi-platform Safety check code in
...@@ -26,25 +25,6 @@ public class SafetyCheckBridge { ...@@ -26,25 +25,6 @@ public class SafetyCheckBridge {
*/ */
@CalledByNative("SafetyCheckCommonObserver") @CalledByNative("SafetyCheckCommonObserver")
void onSafeBrowsingCheckResult(@SafeBrowsingStatus int status); void onSafeBrowsingCheckResult(@SafeBrowsingStatus int status);
/**
* Gets invoked by the C++ code every time another credential is checked.
*
* @param checked Number of passwords already checked.
* @param total Total number of passwords to check.
*/
@CalledByNative("SafetyCheckCommonObserver")
void onPasswordCheckCredentialDone(int checked, int total);
/**
* Gets invoked by the C++ code when the status of the password check changes.
*
* @param state BulkLeakCheckService::State enum value representing the state
* (see //components/password_manager/core/browser
* /bulk_leak_check_service_interface.h).
*/
@CalledByNative("SafetyCheckCommonObserver")
void onPasswordCheckStateChange(@BulkLeakCheckServiceState int state);
} }
/** /**
...@@ -71,37 +51,6 @@ public class SafetyCheckBridge { ...@@ -71,37 +51,6 @@ public class SafetyCheckBridge {
mNativeSafetyCheckBridge, SafetyCheckBridge.this); mNativeSafetyCheckBridge, SafetyCheckBridge.this);
} }
/**
* Triggers the passwords check on the C++ side.
*/
void checkPasswords() {
SafetyCheckBridgeJni.get().checkPasswords(mNativeSafetyCheckBridge, SafetyCheckBridge.this);
}
/**
* @return Number of password leaks discovered during the last check.
*/
int getNumberOfPasswordLeaksFromLastCheck() {
return SafetyCheckBridgeJni.get().getNumberOfPasswordLeaksFromLastCheck(
mNativeSafetyCheckBridge, SafetyCheckBridge.this);
}
/**
* @return Whether the user has some passwords saved.
*/
boolean savedPasswordsExist() {
return SafetyCheckBridgeJni.get().savedPasswordsExist(
mNativeSafetyCheckBridge, SafetyCheckBridge.this);
}
/**
* Stops observing the events of the passwords leak check.
*/
void stopObservingPasswordsCheck() {
SafetyCheckBridgeJni.get().stopObservingPasswordsCheck(
mNativeSafetyCheckBridge, SafetyCheckBridge.this);
}
/** /**
* Destroys the C++ side of the Bridge, freeing up all the associated memory. * Destroys the C++ side of the Bridge, freeing up all the associated memory.
*/ */
...@@ -118,13 +67,6 @@ public class SafetyCheckBridge { ...@@ -118,13 +67,6 @@ public class SafetyCheckBridge {
interface Natives { interface Natives {
long init(SafetyCheckBridge safetyCheckBridge, SafetyCheckCommonObserver observer); long init(SafetyCheckBridge safetyCheckBridge, SafetyCheckCommonObserver observer);
void checkSafeBrowsing(long nativeSafetyCheckBridge, SafetyCheckBridge safetyCheckBridge); void checkSafeBrowsing(long nativeSafetyCheckBridge, SafetyCheckBridge safetyCheckBridge);
void checkPasswords(long nativeSafetyCheckBridge, SafetyCheckBridge safetyCheckBridge);
int getNumberOfPasswordLeaksFromLastCheck(
long nativeSafetyCheckBridge, SafetyCheckBridge safetyCheckBridge);
boolean savedPasswordsExist(
long nativeSafetyCheckBridge, SafetyCheckBridge safetyCheckBridge);
void stopObservingPasswordsCheck(
long nativeSafetyCheckBridge, SafetyCheckBridge safetyCheckBridge);
void destroy(long nativeSafetyCheckBridge, SafetyCheckBridge safetyCheckBridge); void destroy(long nativeSafetyCheckBridge, SafetyCheckBridge safetyCheckBridge);
} }
} }
...@@ -6,7 +6,7 @@ package org.chromium.chrome.browser.safety_check; ...@@ -6,7 +6,7 @@ package org.chromium.chrome.browser.safety_check;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import org.chromium.chrome.browser.password_check.BulkLeakCheckServiceState; import org.chromium.chrome.browser.password_check.PasswordCheckUIStatus;
import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey; import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey;
...@@ -53,20 +53,22 @@ class SafetyCheckProperties { ...@@ -53,20 +53,22 @@ class SafetyCheckProperties {
int ERROR = 8; int ERROR = 8;
} }
static @PasswordsState int passwordsStatefromErrorState(@BulkLeakCheckServiceState int state) { static @PasswordsState int passwordsStatefromErrorState(@PasswordCheckUIStatus int state) {
switch (state) { switch (state) {
case BulkLeakCheckServiceState.SIGNED_OUT: case PasswordCheckUIStatus.ERROR_OFFLINE:
return PasswordsState.OFFLINE;
case PasswordCheckUIStatus.ERROR_NO_PASSWORDS:
return PasswordsState.NO_PASSWORDS;
case PasswordCheckUIStatus.ERROR_SIGNED_OUT:
return PasswordsState.SIGNED_OUT; return PasswordsState.SIGNED_OUT;
case BulkLeakCheckServiceState.QUOTA_LIMIT: case PasswordCheckUIStatus.ERROR_QUOTA_LIMIT:
case PasswordCheckUIStatus.ERROR_QUOTA_LIMIT_ACCOUNT_CHECK:
return PasswordsState.QUOTA_LIMIT; return PasswordsState.QUOTA_LIMIT;
case BulkLeakCheckServiceState.CANCELED: case PasswordCheckUIStatus.CANCELED:
case BulkLeakCheckServiceState.TOKEN_REQUEST_FAILURE: case PasswordCheckUIStatus.ERROR_UNKNOWN:
case BulkLeakCheckServiceState.HASHING_FAILURE:
case BulkLeakCheckServiceState.NETWORK_ERROR:
case BulkLeakCheckServiceState.SERVICE_ERROR:
return PasswordsState.ERROR; return PasswordsState.ERROR;
default: default:
assert false : "Unknown BulkLeakCheckServiceState value."; assert false : "Unknown PasswordCheckUIStatus value.";
} }
// Never reached. // Never reached.
return 0; return 0;
......
...@@ -20,7 +20,6 @@ import org.mockito.MockitoAnnotations; ...@@ -20,7 +20,6 @@ import org.mockito.MockitoAnnotations;
import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.JniMocker; import org.chromium.base.test.util.JniMocker;
import org.chromium.chrome.browser.password_check.BulkLeakCheckServiceState;
import org.chromium.chrome.browser.safety_check.SafetyCheckBridge.SafetyCheckCommonObserver; import org.chromium.chrome.browser.safety_check.SafetyCheckBridge.SafetyCheckCommonObserver;
/** Unit tests for {@link SafetyCheckBridge}. */ /** Unit tests for {@link SafetyCheckBridge}. */
...@@ -28,10 +27,8 @@ import org.chromium.chrome.browser.safety_check.SafetyCheckBridge.SafetyCheckCom ...@@ -28,10 +27,8 @@ import org.chromium.chrome.browser.safety_check.SafetyCheckBridge.SafetyCheckCom
public class SafetyCheckBridgeTest { public class SafetyCheckBridgeTest {
class TestObserver implements SafetyCheckCommonObserver { class TestObserver implements SafetyCheckCommonObserver {
public boolean sbCallbackInvoked; public boolean sbCallbackInvoked;
public boolean passwordsStateChangeInvoked;
private @SafeBrowsingStatus int mSBExpected = -1; private @SafeBrowsingStatus int mSBExpected = -1;
private @BulkLeakCheckServiceState int mPasswordsStateExpected = -1;
@Override @Override
public void onSafeBrowsingCheckResult(@SafeBrowsingStatus int status) { public void onSafeBrowsingCheckResult(@SafeBrowsingStatus int status) {
...@@ -39,22 +36,9 @@ public class SafetyCheckBridgeTest { ...@@ -39,22 +36,9 @@ public class SafetyCheckBridgeTest {
assertEquals(mSBExpected, status); assertEquals(mSBExpected, status);
} }
@Override
public void onPasswordCheckCredentialDone(int checked, int total) {}
@Override
public void onPasswordCheckStateChange(@BulkLeakCheckServiceState int state) {
passwordsStateChangeInvoked = true;
assertEquals(mPasswordsStateExpected, state);
}
public void setSafeBrowsingExpected(@SafeBrowsingStatus int expected) { public void setSafeBrowsingExpected(@SafeBrowsingStatus int expected) {
mSBExpected = expected; mSBExpected = expected;
} }
public void setPasswordsExpected(@BulkLeakCheckServiceState int expected) {
mPasswordsStateExpected = expected;
}
} }
@Rule @Rule
...@@ -91,23 +75,4 @@ public class SafetyCheckBridgeTest { ...@@ -91,23 +75,4 @@ public class SafetyCheckBridgeTest {
assertTrue(mObserver.sbCallbackInvoked); assertTrue(mObserver.sbCallbackInvoked);
} }
@Test
public void testCheckPasswords() {
assertFalse(mObserver.passwordsStateChangeInvoked);
@BulkLeakCheckServiceState
int expected = BulkLeakCheckServiceState.HASHING_FAILURE;
doAnswer(invocation -> {
mObserver.onPasswordCheckStateChange(expected);
return null;
})
.when(mNativeMock)
.checkPasswords(anyLong(), any(SafetyCheckBridge.class));
mObserver.setPasswordsExpected(expected);
mSafetyCheckBridge.checkPasswords();
assertTrue(mObserver.passwordsStateChangeInvoked);
}
} }
...@@ -18,22 +18,28 @@ import androidx.test.filters.SmallTest; ...@@ -18,22 +18,28 @@ import androidx.test.filters.SmallTest;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CallbackHelper;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.password_check.PasswordCheck;
import org.chromium.chrome.browser.password_check.PasswordCheckFactory;
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
import org.chromium.chrome.browser.safety_check.SafetyCheckProperties.SafeBrowsingState; import org.chromium.chrome.browser.safety_check.SafetyCheckProperties.SafeBrowsingState;
import org.chromium.chrome.browser.safety_check.SafetyCheckProperties.UpdatesState; import org.chromium.chrome.browser.safety_check.SafetyCheckProperties.UpdatesState;
import org.chromium.chrome.browser.settings.SettingsActivityTestRule; import org.chromium.chrome.browser.settings.SettingsActivityTestRule;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.util.browser.Features;
import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModel;
/** Tests {@link SafetyCheckSettingsFragment} together with {@link SafetyCheckViewBinder}. */ /** Tests {@link SafetyCheckSettingsFragment} together with {@link SafetyCheckViewBinder}. */
@RunWith(ChromeJUnit4ClassRunner.class) @RunWith(ChromeJUnit4ClassRunner.class)
@Features.EnableFeatures({ChromeFeatureList.SAFETY_CHECK_ANDROID, ChromeFeatureList.PASSWORD_CHECK})
public class SafetyCheckSettingsFragmentTest { public class SafetyCheckSettingsFragmentTest {
private static final String PASSWORDS = "passwords"; private static final String PASSWORDS = "passwords";
private static final String SAFE_BROWSING = "safe_browsing"; private static final String SAFE_BROWSING = "safe_browsing";
...@@ -47,15 +53,22 @@ public class SafetyCheckSettingsFragmentTest { ...@@ -47,15 +53,22 @@ public class SafetyCheckSettingsFragmentTest {
public SettingsActivityTestRule<SafetyCheckSettingsFragment> mSettingsActivityTestRule = public SettingsActivityTestRule<SafetyCheckSettingsFragment> mSettingsActivityTestRule =
new SettingsActivityTestRule<>(SafetyCheckSettingsFragment.class); new SettingsActivityTestRule<>(SafetyCheckSettingsFragment.class);
@Rule
public TestRule mFeaturesProcessor = new Features.JUnitProcessor();
@Mock @Mock
private SafetyCheckBridge mSafetyCheckBridge; private SafetyCheckBridge mSafetyCheckBridge;
@Mock
private PasswordCheck mPasswordCheck;
private PropertyModel mModel; private PropertyModel mModel;
private SafetyCheckSettingsFragment mFragment; private SafetyCheckSettingsFragment mFragment;
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
PasswordCheckFactory.setPasswordCheckForTesting(mPasswordCheck);
} }
@Test @Test
......
...@@ -26,16 +26,11 @@ SafetyCheckBridge::SafetyCheckBridge( ...@@ -26,16 +26,11 @@ SafetyCheckBridge::SafetyCheckBridge(
->GetPrefs()), ->GetPrefs()),
j_safety_check_observer_(j_safety_check_observer) { j_safety_check_observer_(j_safety_check_observer) {
safety_check_.reset(new safety_check::SafetyCheck(this)); safety_check_.reset(new safety_check::SafetyCheck(this));
password_check_controller_.reset(new BulkLeakCheckControllerAndroid());
} }
void SafetyCheckBridge::Destroy( void SafetyCheckBridge::Destroy(
JNIEnv* env, JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj) { const base::android::JavaParamRef<jobject>& obj) {
if (password_check_observed_) {
password_check_controller_->RemoveObserver(this);
}
password_check_controller_.reset();
safety_check_.reset(); safety_check_.reset();
delete this; delete this;
} }
...@@ -46,38 +41,6 @@ void SafetyCheckBridge::CheckSafeBrowsing( ...@@ -46,38 +41,6 @@ void SafetyCheckBridge::CheckSafeBrowsing(
safety_check_->CheckSafeBrowsing(pref_service_); safety_check_->CheckSafeBrowsing(pref_service_);
} }
void SafetyCheckBridge::CheckPasswords(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj) {
// If a password check is already in progress, starting a new one will not
// change the state of the underlying service, so ignore extra requests.
if (password_check_observed_) {
return;
}
password_check_observed_ = true;
password_check_controller_->AddObserver(this);
password_check_controller_->StartPasswordCheck();
}
int SafetyCheckBridge::GetNumberOfPasswordLeaksFromLastCheck(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj) {
return password_check_controller_->GetNumberOfLeaksFromLastCheck();
}
bool SafetyCheckBridge::SavedPasswordsExist(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj) {
return password_check_controller_->GetNumberOfSavedPasswords() != 0;
}
void SafetyCheckBridge::StopObservingPasswordsCheck(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj) {
password_check_controller_->RemoveObserver(this);
password_check_observed_ = false;
}
void SafetyCheckBridge::OnSafeBrowsingCheckResult( void SafetyCheckBridge::OnSafeBrowsingCheckResult(
safety_check::SafetyCheck::SafeBrowsingStatus status) { safety_check::SafetyCheck::SafeBrowsingStatus status) {
JNIEnv* env = base::android::AttachCurrentThread(); JNIEnv* env = base::android::AttachCurrentThread();
...@@ -85,22 +48,4 @@ void SafetyCheckBridge::OnSafeBrowsingCheckResult( ...@@ -85,22 +48,4 @@ void SafetyCheckBridge::OnSafeBrowsingCheckResult(
env, j_safety_check_observer_, static_cast<int>(status)); env, j_safety_check_observer_, static_cast<int>(status));
} }
void SafetyCheckBridge::OnStateChanged(
password_manager::BulkLeakCheckService::State state) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_SafetyCheckCommonObserver_onPasswordCheckStateChange(
env, j_safety_check_observer_, static_cast<int>(state));
}
void SafetyCheckBridge::OnCredentialDone(
const password_manager::LeakCheckCredential& credential,
password_manager::IsLeaked is_leaked,
SafetyCheckBridge::DoneCount credentials_checked,
SafetyCheckBridge::TotalCount total_to_check) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_SafetyCheckCommonObserver_onPasswordCheckCredentialDone(
env, j_safety_check_observer_, credentials_checked.value(),
total_to_check.value());
}
SafetyCheckBridge::~SafetyCheckBridge() = default; SafetyCheckBridge::~SafetyCheckBridge() = default;
...@@ -8,15 +8,13 @@ ...@@ -8,15 +8,13 @@
#include <jni.h> #include <jni.h>
#include "base/android/scoped_java_ref.h" #include "base/android/scoped_java_ref.h"
#include "chrome/browser/password_check/android/bulk_leak_check_controller_android.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
#include "components/safety_check/safety_check.h" #include "components/safety_check/safety_check.h"
// Allows the Java code to make use of cross-platform browser safety checks in // Allows the Java code to make use of cross-platform browser safety checks in
// //components/safety_check. // //components/safety_check.
class SafetyCheckBridge class SafetyCheckBridge
: public safety_check::SafetyCheck::SafetyCheckHandlerInterface, : public safety_check::SafetyCheck::SafetyCheckHandlerInterface {
public BulkLeakCheckControllerAndroid::Observer {
public: public:
// Takes an observer object that will get invoked on check results. // Takes an observer object that will get invoked on check results.
SafetyCheckBridge( SafetyCheckBridge(
...@@ -31,45 +29,15 @@ class SafetyCheckBridge ...@@ -31,45 +29,15 @@ class SafetyCheckBridge
void CheckSafeBrowsing(JNIEnv* env, void CheckSafeBrowsing(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj); const base::android::JavaParamRef<jobject>& obj);
// Checks the passwords and invokes |OnPasswordCheckCredentialDone| and
// |onPasswordCheckStateChange| on the observer.
void CheckPasswords(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
// Returns the number of leaked passwords without running a new check.
int GetNumberOfPasswordLeaksFromLastCheck(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
// Returns whether the user has a non-zero amount of passwords saved.
bool SavedPasswordsExist(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
// Stops observing |BulkLeakCheckControllerAndroid| events.
void StopObservingPasswordsCheck(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
// safety_check::SafetyCheck::SafetyCheckHandlerInterface implementation. // safety_check::SafetyCheck::SafetyCheckHandlerInterface implementation.
void OnSafeBrowsingCheckResult( void OnSafeBrowsingCheckResult(
safety_check::SafetyCheck::SafeBrowsingStatus status) override; safety_check::SafetyCheck::SafeBrowsingStatus status) override;
// BulkLeakCheckControllerAndroid::Observer implementation.
void OnStateChanged(
password_manager::BulkLeakCheckService::State state) override;
void OnCredentialDone(const password_manager::LeakCheckCredential& credential,
password_manager::IsLeaked is_leaked,
DoneCount credentials_checked,
TotalCount total_to_check) override;
private: private:
~SafetyCheckBridge() override; virtual ~SafetyCheckBridge();
PrefService* pref_service_ = nullptr; PrefService* pref_service_ = nullptr;
std::unique_ptr<safety_check::SafetyCheck> safety_check_; std::unique_ptr<safety_check::SafetyCheck> safety_check_;
std::unique_ptr<BulkLeakCheckControllerAndroid> password_check_controller_;
bool password_check_observed_ = false;
base::android::ScopedJavaGlobalRef<jobject> j_safety_check_observer_; base::android::ScopedJavaGlobalRef<jobject> j_safety_check_observer_;
}; };
......
...@@ -4028,7 +4028,6 @@ test("unit_tests") { ...@@ -4028,7 +4028,6 @@ test("unit_tests") {
"//chrome/android/features/media_router:java", "//chrome/android/features/media_router:java",
"//chrome/browser/optimization_guide/android:native_j_unittests_jni_headers", "//chrome/browser/optimization_guide/android:native_j_unittests_jni_headers",
"//chrome/browser/optimization_guide/android:native_java_unittests", "//chrome/browser/optimization_guide/android:native_java_unittests",
"//chrome/browser/password_check/android:unit_tests",
"//chrome/browser/thumbnail:unit_tests", "//chrome/browser/thumbnail:unit_tests",
"//chrome/browser/updates:unit_tests", "//chrome/browser/updates:unit_tests",
"//chrome/services/media_gallery_util:unit_tests", "//chrome/services/media_gallery_util:unit_tests",
......
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