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

import android.content.Context;
import android.os.Bundle;

import androidx.fragment.app.Fragment;

import org.chromium.base.IntentUtils;
import org.chromium.base.supplier.ObservableSupplier;
import org.chromium.base.supplier.OneshotSupplier;
import org.chromium.chrome.browser.LaunchIntentDispatcher;
import org.chromium.chrome.browser.accessibility.settings.AccessibilitySettings;
import org.chromium.chrome.browser.accessibility.settings.ChromeAccessibilitySettingsDelegate;
import org.chromium.chrome.browser.autofill.options.AutofillOptionsCoordinator;
import org.chromium.chrome.browser.autofill.options.AutofillOptionsFragment;
import org.chromium.chrome.browser.autofill.settings.AutofillCreditCardEditor;
import org.chromium.chrome.browser.autofill.settings.AutofillLocalIbanEditor;
import org.chromium.chrome.browser.browsing_data.ClearBrowsingDataFragmentBasic;
import org.chromium.chrome.browser.image_descriptions.ImageDescriptionsController;
import org.chromium.chrome.browser.image_descriptions.ImageDescriptionsSettings;
import org.chromium.chrome.browser.language.settings.LanguageSettings;
import org.chromium.chrome.browser.lifetime.ApplicationLifetime;
import org.chromium.chrome.browser.locale.LocaleManager;
import org.chromium.chrome.browser.page_info.SiteSettingsHelper;
import org.chromium.chrome.browser.password_check.PasswordCheckComponentUiFactory;
import org.chromium.chrome.browser.password_check.PasswordCheckFragmentView;
import org.chromium.chrome.browser.password_entry_edit.CredentialEditUiFactory;
import org.chromium.chrome.browser.password_entry_edit.CredentialEntryFragmentViewBase;
import org.chromium.chrome.browser.password_manager.PasswordManagerHelper;
import org.chromium.chrome.browser.password_manager.PasswordStoreBridge;
import org.chromium.chrome.browser.password_manager.settings.PasswordSettings;
import org.chromium.chrome.browser.privacy_guide.PrivacyGuideFragment;
import org.chromium.chrome.browser.privacy_sandbox.ChromeTrackingProtectionDelegate;
import org.chromium.chrome.browser.privacy_sandbox.PrivacySandboxSettingsBaseFragment;
import org.chromium.chrome.browser.privacy_sandbox.TopicsManageFragment;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.safe_browsing.settings.SafeBrowsingSettingsFragmentBase;
import org.chromium.chrome.browser.safety_check.SafetyCheckBridge;
import org.chromium.chrome.browser.safety_check.SafetyCheckCoordinator;
import org.chromium.chrome.browser.safety_check.SafetyCheckSettingsFragment;
import org.chromium.chrome.browser.safety_check.SafetyCheckUpdatesDelegateImpl;
import org.chromium.chrome.browser.safety_hub.SafetyHubBaseFragment;
import org.chromium.chrome.browser.safety_hub.SafetyHubFragment;
import org.chromium.chrome.browser.safety_hub.SafetyHubModuleDelegateImpl;
import org.chromium.chrome.browser.search_engines.settings.SearchEngineSettings;
import org.chromium.chrome.browser.signin.SigninAndHistorySyncActivityLauncherImpl;
import org.chromium.chrome.browser.signin.SyncConsentActivityLauncherImpl;
import org.chromium.chrome.browser.site_settings.ChromeSiteSettingsDelegate;
import org.chromium.chrome.browser.sync.SyncServiceFactory;
import org.chromium.chrome.browser.sync.settings.AccountManagementFragment;
import org.chromium.chrome.browser.sync.settings.GoogleServicesSettings;
import org.chromium.chrome.browser.sync.settings.ManageSyncSettings;
import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
import org.chromium.components.browser_ui.settings.FragmentSettingsLauncher;
import org.chromium.components.browser_ui.site_settings.BaseSiteSettingsFragment;
import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory;
import org.chromium.components.privacy_sandbox.FingerprintingProtectionSettingsFragment;
import org.chromium.components.privacy_sandbox.IpProtectionSettingsFragment;
import org.chromium.components.privacy_sandbox.TrackingProtectionSettings;
import org.chromium.components.user_prefs.UserPrefs;
import org.chromium.ui.modaldialog.ModalDialogManager;

/** Provides dependencies to fragments in the settings activity. * */
public class FragmentDependencyProvider {
    private final Context mContext;
    private final Profile mProfile;

    // Here are UI dependencies, i.e. objects referencing UI objects (e.g. Views). They are
    // fundamentally circular dependencies because they are needed to construct UI objects.
    // Therefore we use suppliers to provide them once they become available.
    private final OneshotSupplier<SnackbarManager> mSnackbarManagerSupplier;
    private final OneshotSupplier<BottomSheetController> mBottomSheetControllerSupplier;
    private final ObservableSupplier<ModalDialogManager> mModalDialogManagerSupplier;

    public FragmentDependencyProvider(
            Context context,
            Profile profile,
            OneshotSupplier<SnackbarManager> snackbarManagerSupplier,
            OneshotSupplier<BottomSheetController> bottomSheetControllerSupplier,
            ObservableSupplier<ModalDialogManager> modalDialogManagerSupplier) {
        mContext = context;
        mProfile = profile;
        mSnackbarManagerSupplier = snackbarManagerSupplier;
        mBottomSheetControllerSupplier = bottomSheetControllerSupplier;
        mModalDialogManagerSupplier = modalDialogManagerSupplier;
    }

    /**
     * Provides dependencies to a fragment.
     *
     * <p>Call this method on attaching a fragment to an activity.
     */
    public void provide(Fragment fragment) {
        // Common dependencies attachments.
        if (fragment instanceof ProfileDependentSetting) {
            ((ProfileDependentSetting) fragment).setProfile(mProfile);
        }
        if (fragment instanceof FragmentSettingsLauncher) {
            FragmentSettingsLauncher fragmentSettingsLauncher = (FragmentSettingsLauncher) fragment;
            fragmentSettingsLauncher.setSettingsLauncher(
                    SettingsLauncherFactory.createSettingsLauncher());
        }

        // Settings screen specific attachments.
        if (fragment instanceof MainSettings) {
            ((MainSettings) fragment).setModalDialogManagerSupplier(mModalDialogManagerSupplier);
        }
        if (fragment instanceof BaseSiteSettingsFragment) {
            BaseSiteSettingsFragment baseSiteSettingsFragment =
                    ((BaseSiteSettingsFragment) fragment);
            ChromeSiteSettingsDelegate delegate =
                    new ChromeSiteSettingsDelegate(mContext, mProfile);
            delegate.setSnackbarManagerSupplier(mSnackbarManagerSupplier);
            baseSiteSettingsFragment.setSiteSettingsDelegate(delegate);
            baseSiteSettingsFragment.setCustomTabIntentHelper(
                    LaunchIntentDispatcher::createCustomTabActivityIntent);
        }
        if (fragment instanceof SafetyCheckSettingsFragment) {
            SafetyCheckCoordinator.create(
                    (SafetyCheckSettingsFragment) fragment,
                    mProfile,
                    new SafetyCheckUpdatesDelegateImpl(),
                    new SafetyCheckBridge(mProfile),
                    SigninAndHistorySyncActivityLauncherImpl.get(),
                    SyncConsentActivityLauncherImpl.get(),
                    mModalDialogManagerSupplier,
                    SyncServiceFactory.getForProfile(mProfile),
                    UserPrefs.get(mProfile),
                    new PasswordStoreBridge(mProfile),
                    PasswordManagerHelper.getForProfile(mProfile));
        }
        if (fragment instanceof PasswordCheckFragmentView) {
            PasswordCheckComponentUiFactory.create(
                    (PasswordCheckFragmentView) fragment,
                    LaunchIntentDispatcher::createCustomTabActivityIntent,
                    IntentUtils::addTrustedIntentExtras,
                    mProfile);
        }
        if (fragment instanceof CredentialEntryFragmentViewBase) {
            CredentialEditUiFactory.create((CredentialEntryFragmentViewBase) fragment, mProfile);
        }
        if (fragment instanceof SearchEngineSettings) {
            SearchEngineSettings settings = (SearchEngineSettings) fragment;
            settings.setDisableAutoSwitchRunnable(
                    () -> LocaleManager.getInstance().setSearchEngineAutoSwitch(false));
        }
        if (fragment instanceof ImageDescriptionsSettings) {
            ImageDescriptionsSettings imageFragment = (ImageDescriptionsSettings) fragment;
            Bundle extras = imageFragment.getArguments();
            if (extras != null) {
                extras.putBoolean(
                        ImageDescriptionsSettings.IMAGE_DESCRIPTIONS,
                        ImageDescriptionsController.getInstance()
                                .imageDescriptionsEnabled(mProfile));
                extras.putBoolean(
                        ImageDescriptionsSettings.IMAGE_DESCRIPTIONS_DATA_POLICY,
                        ImageDescriptionsController.getInstance().onlyOnWifiEnabled(mProfile));
            }
            imageFragment.setDelegate(ImageDescriptionsController.getInstance().getDelegate());
        }
        if (fragment instanceof PrivacySandboxSettingsBaseFragment) {
            PrivacySandboxSettingsBaseFragment sandboxFragment =
                    (PrivacySandboxSettingsBaseFragment) fragment;
            sandboxFragment.setSnackbarManagerSupplier(mSnackbarManagerSupplier);
            sandboxFragment.setCustomTabIntentHelper(
                    LaunchIntentDispatcher::createCustomTabActivityIntent);
            sandboxFragment.setCookieSettingsIntentHelper(
                    (Context context) -> {
                        SiteSettingsHelper.showCategorySettings(
                                context, SiteSettingsCategory.Type.THIRD_PARTY_COOKIES);
                    });
        }
        if (fragment instanceof SafeBrowsingSettingsFragmentBase) {
            SafeBrowsingSettingsFragmentBase safeBrowsingFragment =
                    (SafeBrowsingSettingsFragmentBase) fragment;
            safeBrowsingFragment.setCustomTabIntentHelper(
                    LaunchIntentDispatcher::createCustomTabActivityIntent);
        }
        if (fragment instanceof LanguageSettings) {
            ((LanguageSettings) fragment)
                    .setRestartAction(
                            () -> {
                                ApplicationLifetime.terminate(true);
                            });
        }
        if (fragment instanceof ClearBrowsingDataFragmentBasic) {
            ((ClearBrowsingDataFragmentBasic) fragment)
                    .setCustomTabIntentHelper(
                            LaunchIntentDispatcher::createCustomTabActivityIntent);
        }
        if (fragment instanceof PrivacyGuideFragment) {
            PrivacyGuideFragment pgFragment = (PrivacyGuideFragment) fragment;
            pgFragment.setBottomSheetControllerSupplier(mBottomSheetControllerSupplier);
            pgFragment.setCustomTabIntentHelper(
                    LaunchIntentDispatcher::createCustomTabActivityIntent);
        }
        if (fragment instanceof AccessibilitySettings) {
            ((AccessibilitySettings) fragment)
                    .setDelegate(new ChromeAccessibilitySettingsDelegate(mProfile));
            ((AccessibilitySettings) fragment).setPrefService(UserPrefs.get(mProfile));
        }
        if (fragment instanceof PasswordSettings) {
            ((PasswordSettings) fragment)
                    .setBottomSheetControllerSupplier(mBottomSheetControllerSupplier);
        }
        if (fragment instanceof AutofillOptionsFragment) {
            AutofillOptionsCoordinator.createFor(
                    (AutofillOptionsFragment) fragment,
                    mModalDialogManagerSupplier,
                    () -> ApplicationLifetime.terminate(true));
        }
        if (fragment instanceof TrackingProtectionSettings) {
            TrackingProtectionSettings tpFragment = ((TrackingProtectionSettings) fragment);
            tpFragment.setTrackingProtectionDelegate(
                    new ChromeTrackingProtectionDelegate(mProfile));
            tpFragment.setCustomTabIntentHelper(
                    LaunchIntentDispatcher::createCustomTabActivityIntent);
        }
        if (fragment instanceof AutofillCreditCardEditor) {
            ((AutofillCreditCardEditor) fragment)
                    .setModalDialogManagerSupplier(mModalDialogManagerSupplier);
        }
        if (fragment instanceof TopicsManageFragment) {
            ((TopicsManageFragment) fragment)
                    .setModalDialogManagerSupplier(mModalDialogManagerSupplier);
        }
        if (fragment instanceof IpProtectionSettingsFragment) {
            IpProtectionSettingsFragment ipProtectionSettingsFragment =
                    ((IpProtectionSettingsFragment) fragment);
            ipProtectionSettingsFragment.setTrackingProtectionDelegate(
                    new ChromeTrackingProtectionDelegate(mProfile));
            ipProtectionSettingsFragment.setCustomTabIntentHelper(
                    LaunchIntentDispatcher::createCustomTabActivityIntent);
        }
        if (fragment
                instanceof FingerprintingProtectionSettingsFragment fpProtectionSettingsFragment) {
            fpProtectionSettingsFragment.setTrackingProtectionDelegate(
                    new ChromeTrackingProtectionDelegate(mProfile));
            fpProtectionSettingsFragment.setCustomTabIntentHelper(
                    LaunchIntentDispatcher::createCustomTabActivityIntent);
        }
        if (fragment instanceof AutofillLocalIbanEditor) {
            ((AutofillLocalIbanEditor) fragment)
                    .setModalDialogManagerSupplier(mModalDialogManagerSupplier);
        }
        if (fragment instanceof SafetyHubFragment safetyHubFragment) {
            safetyHubFragment.setDelegate(
                    new SafetyHubModuleDelegateImpl(
                            mProfile,
                            mModalDialogManagerSupplier,
                            SigninAndHistorySyncActivityLauncherImpl.get(),
                            SyncConsentActivityLauncherImpl.get()));
            // TODO(crbug.com/40751023): Create a shared interface for fragments that need access to
            // LaunchIntentDispatcher::createCustomTabActivityIntent.
            safetyHubFragment.setCustomTabIntentHelper(
                    LaunchIntentDispatcher::createCustomTabActivityIntent);
        }
        if (fragment instanceof AccountManagementFragment) {
            ((AccountManagementFragment) fragment)
                    .setSnackbarManagerSupplier(mSnackbarManagerSupplier);
        }
        if (fragment instanceof GoogleServicesSettings) {
            ((GoogleServicesSettings) fragment)
                    .setSnackbarManagerSupplier(mSnackbarManagerSupplier);
        }
        if (fragment instanceof ManageSyncSettings) {
            ((ManageSyncSettings) fragment).setSnackbarManagerSupplier(mSnackbarManagerSupplier);
        }
        if (fragment instanceof SafetyHubBaseFragment) {
            ((SafetyHubBaseFragment) fragment).setSnackbarManagerSupplier(mSnackbarManagerSupplier);
        }
    }
}