chromium/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAuthUrlHeuristics.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.net.Uri;
import android.text.TextUtils;

import org.chromium.base.metrics.RecordHistogram;

/**
 * Helper class to record histogram to determine whether the Custom Tab was launched with what looks
 * like an OAuth URL.
 */
public class CustomTabAuthUrlHeuristics {
    // Bit flags for potential OAuth params.
    private static final int FLAG_EMPTY = 0;
    private static final int FLAG_CLIENT_ID = 1 << 0;
    private static final int FLAG_REDIRECT_URI = 1 << 1;
    private static final int FLAG_RESPONSE_TYPE = 1 << 2;
    private static final int FLAG_SCOPE = 1 << 3;
    private static final int FLAG_STATE = 1 << 4;

    // Strings for potential OAuth params.
    private static final String CLIENT_ID = "client_id";
    private static final String REDIRECT_URI = "redirect_uri";
    private static final String RESPONSE_TYPE = "response_type";
    private static final String SCOPE = "scope";
    private static final String STATE = "state";

    private static final String CUSTOM_TABS_AUTH_VIEW_URL_PARAMS = "CustomTabs.AuthView.UrlParams";

    /**
     * Extracts potential OAuth params from the provided URL and records a bit field with each bit
     * representing the presence of a param.
     *
     * @param url The url to extract query params from.
     */
    public static void recordUrlParamsHistogram(String url) {
        if (TextUtils.isEmpty(url)) return;
        Uri uri = Uri.parse(url);

        try {
            var params = uri.getQueryParameterNames();

            int flags = FLAG_EMPTY;
            if (params.contains(CLIENT_ID)) {
                flags |= FLAG_CLIENT_ID;
            }
            if (params.contains(REDIRECT_URI)) {
                flags |= FLAG_REDIRECT_URI;
            }
            if (params.contains(RESPONSE_TYPE)) {
                flags |= FLAG_RESPONSE_TYPE;
            }
            if (params.contains(SCOPE)) {
                flags |= FLAG_SCOPE;
            }
            if (params.contains(STATE)) {
                flags |= FLAG_STATE;
            }
            RecordHistogram.recordSparseHistogram(CUSTOM_TABS_AUTH_VIEW_URL_PARAMS, flags);
        } catch (UnsupportedOperationException ignored) {
        }
    }
}