diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillNameFixFlowBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillNameFixFlowBridge.java index 1261bf699c916..2de9bf69f77e4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillNameFixFlowBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillNameFixFlowBridge.java @@ -8,6 +8,8 @@ import static org.chromium.build.NullUtil.assertNonNull; import android.app.Activity; +import androidx.annotation.VisibleForTesting; + import org.jni_zero.CalledByNative; import org.jni_zero.JNINamespace; import org.jni_zero.JniType; @@ -25,7 +27,7 @@ import org.chromium.ui.modaldialog.DialogDismissalCause; @JNINamespace("autofill") @NullMarked final class AutofillNameFixFlowBridge implements AutofillNameFixFlowPromptDelegate { - private final long mNativeCardNameFixFlowViewAndroid; + private long mNativeCardNameFixFlowViewAndroid; private final @Nullable Activity mActivity; private final String mTitle; private final String mInferredName; @@ -33,7 +35,8 @@ final class AutofillNameFixFlowBridge implements AutofillNameFixFlowPromptDelega private final int mIconId; private @Nullable AutofillNameFixFlowPrompt mNameFixFlowPrompt; - private AutofillNameFixFlowBridge( + @VisibleForTesting + AutofillNameFixFlowBridge( long nativeCardNameFixFlowViewAndroid, String title, String inferredName, @@ -74,16 +77,20 @@ final class AutofillNameFixFlowBridge implements AutofillNameFixFlowPromptDelega @Override public void onPromptDismissed() { + if (mNativeCardNameFixFlowViewAndroid == 0) return; AutofillNameFixFlowBridgeJni.get().promptDismissed(mNativeCardNameFixFlowViewAndroid); + mNativeCardNameFixFlowViewAndroid = 0; } @Override public void onUserDismiss() { + if (mNativeCardNameFixFlowViewAndroid == 0) return; AutofillNameFixFlowBridgeJni.get().onUserDismiss(mNativeCardNameFixFlowViewAndroid); } @Override public void onUserAcceptCardholderName(String name) { + if (mNativeCardNameFixFlowViewAndroid == 0) return; AutofillNameFixFlowBridgeJni.get().onUserAccept(mNativeCardNameFixFlowViewAndroid, name); } diff --git a/chrome/android/junit/BUILD.gn b/chrome/android/junit/BUILD.gn index b980f25f63421..d7c8e18261126 100644 --- a/chrome/android/junit/BUILD.gn +++ b/chrome/android/junit/BUILD.gn @@ -505,6 +505,7 @@ if (is_android) { "src/org/chromium/chrome/browser/autofill/AutofillFallbackSurfaceLauncherTest.java", "src/org/chromium/chrome/browser/autofill/AutofillImageFetcherTest.java", "src/org/chromium/chrome/browser/autofill/AutofillImageFetcherUtilsTest.java", + "src/org/chromium/chrome/browser/autofill/AutofillNameFixFlowBridgeTest.java", "src/org/chromium/chrome/browser/autofill/AutofillUiUtilsTest.java", "src/org/chromium/chrome/browser/autofill/CardUnmaskBridgeTest.java", "src/org/chromium/chrome/browser/autofill/GoogleWalletLauncherTest.java", diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/AutofillNameFixFlowBridgeTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/AutofillNameFixFlowBridgeTest.java new file mode 100644 index 0000000000000..af171f278be7e --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/AutofillNameFixFlowBridgeTest.java @@ -0,0 +1,112 @@ +// Copyright 2026 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.autofill; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import android.app.Activity; + +import androidx.test.filters.SmallTest; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.Robolectric; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.ui.base.WindowAndroid; + +/** Unit tests for {@link AutofillNameFixFlowBridge}. */ +@SmallTest +@RunWith(BaseRobolectricTestRunner.class) +public final class AutofillNameFixFlowBridgeTest { + private static final long NATIVE_POINTER = 0x1234abcdL; + + @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); + + @Mock private AutofillNameFixFlowBridge.Natives mNativeMock; + + private WindowAndroid mWindowAndroid; + private AutofillNameFixFlowBridge mBridge; + + @Before + public void setUp() { + AutofillNameFixFlowBridgeJni.setInstanceForTesting(mNativeMock); + + Activity activity = Robolectric.buildActivity(Activity.class).create().get(); + mWindowAndroid = new WindowAndroid(activity, /* occlusionTrackingAllowed= */ false); + + mBridge = + new AutofillNameFixFlowBridge( + NATIVE_POINTER, + /* title= */ "Title", + /* inferredName= */ "Jane Doe", + /* confirmButtonLabel= */ "Confirm", + /* iconId= */ 0, + mWindowAndroid); + } + + @After + public void tearDown() { + mWindowAndroid.destroy(); + } + + @Test + public void testOnUserAcceptCardholderName_callsNative() { + mBridge.onUserAcceptCardholderName("Jane Doe"); + + verify(mNativeMock).onUserAccept(NATIVE_POINTER, "Jane Doe"); + } + + @Test + public void testOnUserDismiss_callsNative() { + mBridge.onUserDismiss(); + + verify(mNativeMock).onUserDismiss(NATIVE_POINTER); + } + + @Test + public void testOnPromptDismissed_callsNative() { + mBridge.onPromptDismissed(); + + verify(mNativeMock).promptDismissed(NATIVE_POINTER); + } + + @Test + public void testOnUserAcceptCardholderName_afterPromptDismissed_doesNotCallNative() { + mBridge.onPromptDismissed(); + verify(mNativeMock).promptDismissed(NATIVE_POINTER); + + mBridge.onUserAcceptCardholderName("Jane Doe"); + + verifyNoMoreInteractions(mNativeMock); + } + + @Test + public void testOnUserDismiss_afterPromptDismissed_doesNotCallNative() { + mBridge.onPromptDismissed(); + verify(mNativeMock).promptDismissed(NATIVE_POINTER); + + mBridge.onUserDismiss(); + + verifyNoMoreInteractions(mNativeMock); + } + + @Test + public void testOnPromptDismissed_afterPromptDismissed_doesNotCallNative() { + mBridge.onPromptDismissed(); + verify(mNativeMock).promptDismissed(NATIVE_POINTER); + + mBridge.onPromptDismissed(); + + verifyNoMoreInteractions(mNativeMock); + } +}