chromium/components/feature_engagement/internal/android/java/src/org/chromium/components/feature_engagement/internal/TrackerImpl.java

// Copyright 2017 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.components.feature_engagement.internal;

import androidx.annotation.CheckResult;
import androidx.annotation.Nullable;

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

import org.chromium.base.Callback;
import org.chromium.base.CommandLine;
import org.chromium.components.feature_engagement.Tracker;
import org.chromium.components.feature_engagement.TriggerDetails;
import org.chromium.components.feature_engagement.TriggerState;
import org.chromium.ui.UiSwitches;

/**
 * Java side of the JNI bridge between TrackerImpl in Java
 * and C++. All method calls are delegated to the native C++ class.
 */
@JNINamespace("feature_engagement")
public class TrackerImpl implements Tracker {
    /**
     * A JNI-wrapper for the native DisplayLockHandle.
     * The C++ counterpart is DisplayLockHandleAndroid.
     */
    static class DisplayLockHandleAndroid implements DisplayLockHandle {
        @CalledByNative("DisplayLockHandleAndroid")
        private static DisplayLockHandleAndroid create(long nativePtr) {
            return new DisplayLockHandleAndroid(nativePtr);
        }

        long mNativePtr;

        private DisplayLockHandleAndroid(long nativePtr) {
            mNativePtr = nativePtr;
        }

        @CalledByNative("DisplayLockHandleAndroid")
        private void clearNativePtr() {
            mNativePtr = 0;
        }

        @Override
        public void release() {
            assert mNativePtr != 0;
            TrackerImplJni.get().release(mNativePtr);
            assert mNativePtr == 0;
        }
    }

    /** The pointer to the feature_engagement::TrackerImplAndroid JNI bridge. */
    private long mNativePtr;

    @CalledByNative
    private static TrackerImpl create(long nativePtr) {
        return new TrackerImpl(nativePtr);
    }

    private TrackerImpl(long nativePtr) {
        mNativePtr = nativePtr;
    }

    @Override
    public void notifyEvent(String event) {
        assert mNativePtr != 0;
        TrackerImplJni.get().notifyEvent(mNativePtr, TrackerImpl.this, event);
    }

    @Override
    public boolean shouldTriggerHelpUI(String feature) {
        // Disable all IPH if the UI is in screenshot mode. For context, see crbug.com/964012.
        if (CommandLine.getInstance().hasSwitch(UiSwitches.ENABLE_SCREENSHOT_UI_MODE)) {
            return false;
        }

        assert mNativePtr != 0;
        return TrackerImplJni.get().shouldTriggerHelpUI(mNativePtr, TrackerImpl.this, feature);
    }

    @Override
    public TriggerDetails shouldTriggerHelpUIWithSnooze(String feature) {
        // Disable all IPH if the UI is in screenshot mode. For context, see crbug.com/964012.
        if (CommandLine.getInstance().hasSwitch(UiSwitches.ENABLE_SCREENSHOT_UI_MODE)) {
            return new TriggerDetails(false, false);
        }
        assert mNativePtr != 0;
        return TrackerImplJni.get()
                .shouldTriggerHelpUIWithSnooze(mNativePtr, TrackerImpl.this, feature);
    }

    @Override
    public boolean wouldTriggerHelpUI(String feature) {
        assert mNativePtr != 0;
        return TrackerImplJni.get().wouldTriggerHelpUI(mNativePtr, TrackerImpl.this, feature);
    }

    @Override
    public boolean hasEverTriggered(String feature, boolean fromWindow) {
        assert mNativePtr != 0;
        return TrackerImplJni.get()
                .hasEverTriggered(mNativePtr, TrackerImpl.this, feature, fromWindow);
    }

    @Override
    @TriggerState
    public int getTriggerState(String feature) {
        assert mNativePtr != 0;
        return TrackerImplJni.get().getTriggerState(mNativePtr, TrackerImpl.this, feature);
    }

    @Override
    public void dismissed(String feature) {
        assert mNativePtr != 0;
        TrackerImplJni.get().dismissed(mNativePtr, TrackerImpl.this, feature);
    }

    @Override
    public void dismissedWithSnooze(String feature, int snoozeAction) {
        assert mNativePtr != 0;
        TrackerImplJni.get()
                .dismissedWithSnooze(mNativePtr, TrackerImpl.this, feature, snoozeAction);
    }

    @Override
    @CheckResult
    @Nullable
    public DisplayLockHandle acquireDisplayLock() {
        assert mNativePtr != 0;
        return TrackerImplJni.get().acquireDisplayLock(mNativePtr, TrackerImpl.this);
    }

    @Override
    public void setPriorityNotification(String feature) {
        TrackerImplJni.get().setPriorityNotification(mNativePtr, TrackerImpl.this, feature);
    }

    @Override
    @Nullable
    public String getPendingPriorityNotification() {
        return TrackerImplJni.get().getPendingPriorityNotification(mNativePtr, TrackerImpl.this);
    }

    @Override
    public void registerPriorityNotificationHandler(
            String feature, Runnable priorityNotificationHandler) {
        TrackerImplJni.get()
                .registerPriorityNotificationHandler(
                        mNativePtr, TrackerImpl.this, feature, priorityNotificationHandler);
    }

    @Override
    public void unregisterPriorityNotificationHandler(String feature) {
        TrackerImplJni.get()
                .unregisterPriorityNotificationHandler(mNativePtr, TrackerImpl.this, feature);
    }

    @Override
    public boolean isInitialized() {
        assert mNativePtr != 0;
        return TrackerImplJni.get().isInitialized(mNativePtr, TrackerImpl.this);
    }

    @Override
    public void addOnInitializedCallback(Callback<Boolean> callback) {
        assert mNativePtr != 0;
        TrackerImplJni.get().addOnInitializedCallback(mNativePtr, TrackerImpl.this, callback);
    }

    @CalledByNative
    private void clearNativePtr() {
        mNativePtr = 0;
    }

    @CalledByNative
    private long getNativePtr() {
        assert mNativePtr != 0;
        return mNativePtr;
    }

    @CalledByNative
    private static TriggerDetails createTriggerDetails(
            boolean shouldTriggerIph, boolean shouldShowSnooze) {
        return new TriggerDetails(shouldTriggerIph, shouldShowSnooze);
    }

    @NativeMethods
    interface Natives {
        void notifyEvent(long nativeTrackerImplAndroid, TrackerImpl caller, String event);

        boolean shouldTriggerHelpUI(
                long nativeTrackerImplAndroid, TrackerImpl caller, String feature);

        TriggerDetails shouldTriggerHelpUIWithSnooze(
                long nativeTrackerImplAndroid, TrackerImpl caller, String feature);

        boolean wouldTriggerHelpUI(
                long nativeTrackerImplAndroid, TrackerImpl caller, String feature);

        boolean hasEverTriggered(
                long nativeTrackerImplAndroid,
                TrackerImpl caller,
                String feature,
                boolean fromWindow);

        int getTriggerState(long nativeTrackerImplAndroid, TrackerImpl caller, String feature);

        void dismissed(long nativeTrackerImplAndroid, TrackerImpl caller, String feature);

        void dismissedWithSnooze(
                long nativeTrackerImplAndroid,
                TrackerImpl caller,
                String feature,
                int snoozeAction);

        DisplayLockHandleAndroid acquireDisplayLock(
                long nativeTrackerImplAndroid, TrackerImpl caller);

        void setPriorityNotification(
                long nativeTrackerImplAndroid, TrackerImpl caller, String feature);

        String getPendingPriorityNotification(long nativeTrackerImplAndroid, TrackerImpl caller);

        void registerPriorityNotificationHandler(
                long nativeTrackerImplAndroid,
                TrackerImpl caller,
                String feature,
                Runnable priorityNotificationHandler);

        void unregisterPriorityNotificationHandler(
                long nativeTrackerImplAndroid, TrackerImpl caller, String feature);

        boolean isInitialized(long nativeTrackerImplAndroid, TrackerImpl caller);

        void addOnInitializedCallback(
                long nativeTrackerImplAndroid, TrackerImpl caller, Callback<Boolean> callback);

        void release(long nativeDisplayLockHandleAndroid);
    }
}