chromium/chrome/android/java/src/org/chromium/chrome/browser/customtabs/AuthTabIntentDataProvider.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.customtabs;

import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.OptIn;
import androidx.browser.auth.AuthTabIntent;
import androidx.browser.auth.ExperimentalAuthTab;
import androidx.browser.customtabs.CustomTabsIntent;

import org.chromium.base.IntentUtils;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.IntentHandler;
import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider;
import org.chromium.chrome.browser.browserservices.intents.ColorProvider;
import org.chromium.chrome.browser.flags.ActivityType;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.components.browser_ui.widget.TintedDrawable;

/**
 * A model class that parses the incoming intent for Auth Tab specific data.
 *
 * <p>Lifecycle: is activity-scoped, i.e. one instance per CustomTabActivity instance. Must be
 * re-created when color scheme changes, which happens automatically since color scheme change leads
 * to activity re-creation.
 */
@OptIn(markerClass = ExperimentalAuthTab.class)
public class AuthTabIntentDataProvider extends BrowserServicesIntentDataProvider {
    private final @NonNull Intent mIntent;
    private final @Nullable String mClientPackageName;
    private final @NonNull ColorProvider mColorProvider;
    private final @NonNull Drawable mCloseButtonIcon;
    private final @Nullable String mRedirectScheme;

    @Nullable private String mUrlToLoad;

    public static boolean isAuthTabIntent(Intent intent) {
        if (!ChromeFeatureList.sCctAuthTab.isEnabled()) return false;
        return IntentUtils.safeGetBooleanExtra(intent, AuthTabIntent.EXTRA_LAUNCH_AUTH_TAB, false);
    }

    /**
     * Constructs an {@link AuthTabIntentDataProvider}.
     *
     * @param intent The {@link Intent} to launch the Auth Tab.
     * @param context The {@link Context}.
     */
    public AuthTabIntentDataProvider(Intent intent, Context context) {
        assert intent != null;
        mIntent = intent;
        mClientPackageName =
                IntentUtils.safeGetStringExtra(
                        intent, IntentHandler.EXTRA_CALLING_ACTIVITY_PACKAGE);
        mColorProvider = new AuthTabColorProvider(context);
        mCloseButtonIcon = TintedDrawable.constructTintedDrawable(context, R.drawable.btn_close);
        // TODO(crbug.com/353586171): We should disallow http/https and other known schemes such as
        // content://, file://, chrome:// etc. Can be handled using methods in UrlUtilities, but we
        // might want to disallow more.
        mRedirectScheme =
                IntentUtils.safeGetStringExtra(intent, AuthTabIntent.EXTRA_REDIRECT_SCHEME);
    }

    @Override
    public @ActivityType int getActivityType() {
        return ActivityType.AUTH_TAB;
    }

    @Override
    public Intent getIntent() {
        return mIntent;
    }

    @Override
    public String getClientPackageName() {
        return mClientPackageName;
    }

    @Override
    public String getUrlToLoad() {
        if (mUrlToLoad == null) {
            mUrlToLoad = IntentHandler.getUrlFromIntent(mIntent);
        }
        return mUrlToLoad;
    }

    @Override
    public boolean shouldEnableUrlBarHiding() {
        return false;
    }

    @Override
    public ColorProvider getColorProvider() {
        return mColorProvider;
    }

    @Nullable
    @Override
    public Drawable getCloseButtonDrawable() {
        return mCloseButtonIcon;
    }

    @Override
    public int getTitleVisibilityState() {
        return CustomTabsIntent.SHOW_PAGE_TITLE;
    }

    @Override
    public @CustomTabsUiType int getUiType() {
        return CustomTabsUiType.AUTH_TAB;
    }

    @Override
    public boolean shouldShowStarButton() {
        return false;
    }

    @Override
    public boolean shouldShowDownloadButton() {
        return false;
    }

    @Override
    public @CustomTabProfileType int getCustomTabMode() {
        // TODO(crbug.com/359315737): Handle properly once the relevant code lands in AndroidX.
        return CustomTabProfileType.REGULAR;
    }

    @Override
    public boolean isAuthTab() {
        return true;
    }

    @Override
    public String getAuthRedirectScheme() {
        return mRedirectScheme;
    }
}