chromium/chrome/browser/ui/android/digital_credentials/java/src/org/chromium/chrome/browser/ui/android/digital_credentials/DigitalIdentitySafetyInterstitialBridge.java

// Copyright 2024 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.ui.android.digital_credentials;

import android.app.Activity;

import org.jni_zero.CalledByNative;
import org.jni_zero.NativeMethods;

import org.chromium.base.metrics.RecordHistogram;
import org.chromium.chrome.browser.digital_credentials.DigitalIdentityInterstitialClosedReason;
import org.chromium.content_public.browser.webid.DigitalIdentityInterstitialType;
import org.chromium.content_public.browser.webid.DigitalIdentityRequestStatusForMetrics;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.modaldialog.DialogDismissalCause;
import org.chromium.ui.modaldialog.ModalDialogManager;
import org.chromium.ui.modaldialog.ModalDialogManagerHolder;
import org.chromium.url.Origin;

/**
 * Initiates showing modal dialog asking user whether they want to share their identity with
 * website.
 */
public class DigitalIdentitySafetyInterstitialBridge {
    private long mNativeDigitalIdentitySafetyInterstitialBridgeAndroid;

    private DigitalIdentitySafetyInterstitialController mController;

    private DigitalIdentitySafetyInterstitialBridge(
            long digitalIdentitySafetyInterstitialBridgeAndroid) {
        mNativeDigitalIdentitySafetyInterstitialBridgeAndroid =
                digitalIdentitySafetyInterstitialBridgeAndroid;
    }

    @CalledByNative
    public static DigitalIdentitySafetyInterstitialBridge create(
            long digitalIdentitySafetyInterstitialBridgeAndroid) {
        return new DigitalIdentitySafetyInterstitialBridge(
                digitalIdentitySafetyInterstitialBridgeAndroid);
    }

    @CalledByNative
    private void destroy() {
        mNativeDigitalIdentitySafetyInterstitialBridgeAndroid = 0;
        mController = null;
    }

    @CalledByNative
    public void showInterstitial(
            WindowAndroid window,
            Origin origin,
            @DigitalIdentityInterstitialType int interstitialType) {
        if (window == null) {
            onDone(DigitalIdentityRequestStatusForMetrics.ERROR_OTHER);
            return;
        }

        Activity activity = window.getActivity().get();
        ModalDialogManager modalDialogManager =
                (activity instanceof ModalDialogManagerHolder)
                        ? ((ModalDialogManagerHolder) activity).getModalDialogManager()
                        : null;

        if (modalDialogManager == null) {
            onDone(DigitalIdentityRequestStatusForMetrics.ERROR_OTHER);
            return;
        }

        mController = new DigitalIdentitySafetyInterstitialController(origin);
        mController.show(
                modalDialogManager,
                interstitialType,
                (/*DialogDismissalCause*/ Integer dismissalCause) -> {
                    RecordHistogram.recordEnumeratedHistogram(
                            "Blink.DigitalIdentityRequest.InterstitialClosedReason",
                            closedReasonFromDismissalCause(dismissalCause),
                            DigitalIdentityInterstitialClosedReason.MAX_VALUE + 1);
                    onDone(
                            dismissalCause.intValue()
                                            == DialogDismissalCause.POSITIVE_BUTTON_CLICKED
                                    ? DigitalIdentityRequestStatusForMetrics.SUCCESS
                                    : DigitalIdentityRequestStatusForMetrics.ERROR_USER_DECLINED);
                });
    }

    @CalledByNative
    public void abort() {
        if (mController != null) {
            mController.abort();
        }
    }

    public void onDone(@DigitalIdentityRequestStatusForMetrics int statusForMetrics) {
        mController = null;

        if (mNativeDigitalIdentitySafetyInterstitialBridgeAndroid != 0) {
            DigitalIdentitySafetyInterstitialBridgeJni.get()
                    .onInterstitialDone(
                            mNativeDigitalIdentitySafetyInterstitialBridgeAndroid,
                            statusForMetrics);
        }
    }

    private static @DigitalIdentityInterstitialClosedReason int closedReasonFromDismissalCause(
            Integer dismissalCause) {
        switch (dismissalCause) {
            case DialogDismissalCause.POSITIVE_BUTTON_CLICKED:
                return DigitalIdentityInterstitialClosedReason.OK_BUTTON;
            case DialogDismissalCause.NEGATIVE_BUTTON_CLICKED:
                return DigitalIdentityInterstitialClosedReason.CANCEL_BUTTON;
            case DialogDismissalCause.NAVIGATE:
                return DigitalIdentityInterstitialClosedReason.PAGE_NAVIGATED;
            default:
                return DigitalIdentityInterstitialClosedReason.OTHER;
        }
    }

    @NativeMethods
    interface Natives {
        void onInterstitialDone(
                long nativeDigitalIdentitySafetyInterstitialBridgeAndroid,
                @DigitalIdentityRequestStatusForMetrics int statusForMetrics);
    }
}