chromium/chrome/browser/ui/android/hats/internal/java/src/org/chromium/chrome/browser/ui/hats/SurveyClientBridge.java

// Copyright 2023 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.hats;

import android.app.Activity;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;

import org.jni_zero.CalledByNative;
import org.jni_zero.JNINamespace;

import org.chromium.base.Log;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcherProvider;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.ui.base.WindowAndroid;

import java.util.HashMap;
import java.util.Map;

/**
 * Glue code that's used to pass C++ initiated SurveyClient to Java. Thus, this class should not be
 * initialized from Java.
 */
@JNINamespace("hats")
class SurveyClientBridge implements SurveyClient {
    private static final String TAG = "SurveyClient";

    private @NonNull final SurveyClient mDelegate;
    private final long mNativeSurveyClient;

    private SurveyClientBridge(long nativeSurveyClient, @NonNull SurveyClient delegate) {
        mNativeSurveyClient = nativeSurveyClient;
        mDelegate = delegate;
    }

    @CalledByNative
    @VisibleForTesting
    static SurveyClientBridge create(
            long nativeSurveyClient,
            String trigger,
            SurveyUiDelegate uiDelegate,
            Profile profile,
            String suppliedTriggerId) {
        assert SurveyClientFactory.getInstance() != null;
        SurveyConfig config = SurveyConfig.get(trigger, suppliedTriggerId);
        if (config == null) {
            return null;
        }

        SurveyClient client =
                SurveyClientFactory.getInstance().createClient(config, uiDelegate, profile);
        if (client == null) {
            Log.d(TAG, "SurveyClient is null. config: " + SurveyConfig.toString(config));
            return null;
        }
        return new SurveyClientBridge(nativeSurveyClient, client);
    }

    /**
     * Called from Java to show a survey without PSD. Used if SurveyUiDelegate is created from C++.
     */
    @Override
    public void showSurvey(Activity activity, ActivityLifecycleDispatcher lifecycleDispatcher) {
        mDelegate.showSurvey(activity, lifecycleDispatcher);
    }

    /** Called from Java to show a survey with PSD. Used if SurveyUiDelegate is created from C++. */
    @Override
    public void showSurvey(
            Activity activity,
            ActivityLifecycleDispatcher lifecycleDispatcher,
            Map<String, Boolean> surveyPsdBitValues,
            Map<String, String> surveyPsdStringValues) {
        mDelegate.showSurvey(
                activity, lifecycleDispatcher, surveyPsdBitValues, surveyPsdStringValues);
    }

    /** Called when a C++ client wants to display a survey with PSD. */
    @CalledByNative
    void showSurvey(
            WindowAndroid windowAndroid,
            String[] surveyPsdBitFields,
            boolean[] surveyPsdBitValues,
            String[] surveyPsdStringFields,
            String[] surveyPsdStringValues) {
        assert surveyPsdBitFields.length == surveyPsdBitValues.length;
        assert surveyPsdStringFields.length == surveyPsdStringValues.length;

        Map<String, Boolean> bitsValues = new HashMap<>();
        for (int i = 0; i < surveyPsdBitFields.length; ++i) {
            bitsValues.put(surveyPsdBitFields[i], surveyPsdBitValues[i]);
        }
        Map<String, String> stringValues = new HashMap<>();
        for (int i = 0; i < surveyPsdStringFields.length; ++i) {
            stringValues.put(surveyPsdStringFields[i], surveyPsdStringValues[i]);
        }

        Activity activity = windowAndroid.getActivity().get();
        ActivityLifecycleDispatcher lifecycleDispatcher = null;
        if (activity instanceof ActivityLifecycleDispatcherProvider) {
            // TODO(crbug/326643655): Allow access ActivityLifecycleDispatcher from WindowAndroid.
            lifecycleDispatcher =
                    ((ActivityLifecycleDispatcherProvider) activity).getLifecycleDispatcher();
        }
        showSurvey(activity, lifecycleDispatcher, bitsValues, stringValues);
    }
}