// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/chrome_features.h"

#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/strings/string_split.h"
#include "base/time/time.h"
#include "build/android_buildflags.h"
#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "chrome/common/chrome_switches.h"
#include "pdf/buildflags.h"

namespace features {

// All features in alphabetical order.

// Timeout controlling how long the paint stability monitor waits after the
// initial contentful paint before considering the UI to have stabilized.
const base::FeatureParam<base::TimeDelta>
    kActorPaintStabilityIntialPaintTimeout{
        &kGlicActor, "actor-paint-stability-initial-paint-timeout",
        base::Seconds(1)};
// Timeout controlling how long the paint stability monitor waits for subsequent
// contenful paints before considering the UI to have stabilized.
const base::FeatureParam<base::TimeDelta>
    kActorPaintStabilitySubsequentPaintTimeout{
        &kGlicActor, "actor-paint-stability-subsequent-paint-timeout",
        base::Seconds(1)};

#if BUILDFLAG(IS_WIN)
// When enabled, notifications from PWA's will use the PWA icon and name,
// as long as the PWA is on the start menu.  b/40285965.
BASE_FEATURE(kAppSpecificNotifications, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kDisableBoostPriority, base::FEATURE_DISABLED_BY_DEFAULT);

#endif  // BUILDFLAG(IS_WIN)

#if BUILDFLAG(IS_MAC)
// Can be used to disable RemoteCocoa (hosting NSWindows for apps in the app
// process). For debugging purposes only.
BASE_FEATURE(kAppShimRemoteCocoa, base::FEATURE_ENABLED_BY_DEFAULT);

// This is used to control the new app close behavior on macOS wherein closing
// all windows for an app leaves the app running.
// https://crbug.com/40130206
BASE_FEATURE(kAppShimNewCloseBehavior, base::FEATURE_DISABLED_BY_DEFAULT);

// When enabled, app shims try to launch chrome silently if chrome isn't already
// running, rather than have chrome launch visibly with a new tab/profile
// selector.
// https://crbug.com/40180521
BASE_FEATURE(kAppShimLaunchChromeSilently, base::FEATURE_ENABLED_BY_DEFAULT);

// When enabled, notifications coming from PWAs will be displayed via their app
// shim processes, rather than directly by chrome.
// https://crbug.com/40616749
BASE_FEATURE(kAppShimNotificationAttribution,
             base::FEATURE_DISABLED_BY_DEFAULT);

// When enabled, app shims used by PWAs will be signed with an ad-hoc signature
// https://crbug.com/40276068
BASE_FEATURE(kUseAdHocSigningForWebAppShims, base::FEATURE_ENABLED_BY_DEFAULT);

// When enabled, the KeychainKeyProvider is used to provide the OS Crypt async
// key.
BASE_FEATURE(kUseKeychainKeyProvider, base::FEATURE_ENABLED_BY_DEFAULT);
#endif  // BUILDFLAG(IS_MAC)

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
    BUILDFLAG(IS_CHROMEOS)
// Enables or disables the Autofill survey triggered by opening a prompt to
// save address info.
BASE_FEATURE(kAutofillAddressSurvey, base::FEATURE_DISABLED_BY_DEFAULT);
// Enables or disables the Autofill survey triggered by opening a prompt to
// save credit card info.
BASE_FEATURE(kAutofillCardSurvey, base::FEATURE_DISABLED_BY_DEFAULT);
// Enables or disables the Autofill survey triggered by opening a prompt to
// save password info.
BASE_FEATURE(kAutofillPasswordSurvey, base::FEATURE_DISABLED_BY_DEFAULT);
#endif

#if BUILDFLAG(IS_ANDROID)
// When enabled, GetUserCacheDirectory on Android will append the relative path
// of non-default partitions to the cache directory.
BASE_FEATURE(kAndroidKeepProfilePartitionDirsInCacheDir,
             base::FEATURE_ENABLED_BY_DEFAULT);

// Enable boarding pass detector on Chrome Android.
BASE_FEATURE(kBoardingPassDetector, base::FEATURE_DISABLED_BY_DEFAULT);
const char kBoardingPassDetectorUrlParamName[] = "boarding_pass_detector_urls";
const base::FeatureParam<std::string> kBoardingPassDetectorUrlParam(
    &kBoardingPassDetector,
    kBoardingPassDetectorUrlParamName,
    "");
#endif  // BUILDFLAG(IS_ANDROID)

#if BUILDFLAG(IS_CHROMEOS)
// Enable Borealis on Chrome OS.
BASE_FEATURE(kBorealis, base::FEATURE_DISABLED_BY_DEFAULT);
#endif

#if !BUILDFLAG(IS_ANDROID)
BASE_FEATURE(kCaptureHandleForStandalonePwasAndIwas,
             base::FEATURE_DISABLED_BY_DEFAULT);
#endif  // !BUILDFLAG(IS_ANDROID)

#if BUILDFLAG(IS_CHROMEOS)
// Enable project Crostini, Linux VMs on Chrome OS.
BASE_FEATURE(kCrostini, base::FEATURE_DISABLED_BY_DEFAULT);

// If enabled, use the restricted/unified locked state controller.
BASE_FEATURE(kUseUnifiedLockedStateController,
             base::FEATURE_DISABLED_BY_DEFAULT);

bool IsUseUnifiedLockedStateControllerEnabled() {
  return base::FeatureList::IsEnabled(kUseUnifiedLockedStateController);
}
#endif  // BUILDFLAG(IS_CHROMEOS)

// Enables stricter cryptography settings for CNSA2 compliance. This is not
// needed for security, but may be required by some organizations.
BASE_FEATURE(kCryptographyComplianceCnsa, base::FEATURE_DISABLED_BY_DEFAULT);

// Delays BEST_EFFORT tasks during startup until tabs are loaded/idle and first
// paint.
BASE_FEATURE(kImprovedStartupBestEffortDelay,
             base::FEATURE_DISABLED_BY_DEFAULT);

// Sets the timeout until startup is declared "finished" even if not all
// StartupInProgressRefs have been dropped.
BASE_FEATURE_PARAM(base::TimeDelta,
                   kStartupDelayFailsafeTimeout,
                   &kImprovedStartupBestEffortDelay,
                   base::Minutes(3));

// Sets the timeout until the startup observer stops waiting for a visible tab.
// This can happen if a dialog is shown on start (eg. the profile picker), or in
// Mac's zero-window mode. If a tab appears before this timeout, the observer
// waits for it to fully load. If this is 0, the startup observer won't wait for
// tabs to become loaded/idle.
//
// The default matches kWaitingForNavigationTimeout because before the
// kImprovedStartupBestEffortDelay feature, many startups were marked "finished"
// at that point.
BASE_FEATURE_PARAM(base::TimeDelta,
                   kStartupDelayVisibleTabTimeout,
                   &kImprovedStartupBestEffortDelay,
                   base::Seconds(5));

// If true, the startup observer will consider a tab "finished" if it reaches
// the kLoadingTimedOut state, instead of just kLoadedIdle.
BASE_FEATURE_PARAM(bool,
                   kStartupDelayStopOnLoadingTimedOut,
                   &kImprovedStartupBestEffortDelay,
                   false);

// If true, session restore will create a StartupInProgressRef, and drop it when
// restore is finished.
BASE_FEATURE_PARAM(bool,
                   kStartupDelayIncludesSessionRestore,
                   &kImprovedStartupBestEffortDelay,
                   true);

#if !BUILDFLAG(IS_ANDROID)
// Whether to allow installed-by-default web apps to be installed or not.
BASE_FEATURE(kPreinstalledWebAppInstallation,
             "DefaultWebAppInstallation",
             base::FEATURE_ENABLED_BY_DEFAULT);

// Whether to force migrate preinstalled web apps whenever the old Chrome app
// they're replacing is detected, even if the web app is already installed.
// Used by unit tests.
BASE_FEATURE(kPreinstalledWebAppAlwaysMigrateForTesting,
             base::FEATURE_DISABLED_BY_DEFAULT);
#endif

#if !BUILDFLAG(IS_ANDROID)
BASE_FEATURE(kRemoteActorCredentialSharing, base::FEATURE_DISABLED_BY_DEFAULT);
// This parameter is for testing purposes only and must not be used in
// production. It overrides the whitelisted origins with the specified host.
const base::FeatureParam<std::string>
    kRemoteActorCredentialSharingAllowedHostForTesting{
        &kRemoteActorCredentialSharing, "allowed_host_for_testing", ""};
#endif

bool RemoteActorCredentialSharingEnabled() {
#if !BUILDFLAG(IS_ANDROID)
  return base::FeatureList::IsEnabled(features::kRemoteActorCredentialSharing);
#else
  return false;
#endif
}

// Controls the enablement of structured metrics on Windows, Linux, and Mac.
BASE_FEATURE(kChromeStructuredMetrics, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kDeferSpellcheckInitialization, base::FEATURE_DISABLED_BY_DEFAULT);

// Moves the Extensions "puzzle piece" icon from the title bar into the app menu
// for web app windows.
BASE_FEATURE(kDesktopPWAsElidedExtensionsMenu,
#if BUILDFLAG(IS_CHROMEOS)
             base::FEATURE_ENABLED_BY_DEFAULT
#else
             base::FEATURE_DISABLED_BY_DEFAULT
#endif
);

// If enabled, allow-listed PWAs cannot be closed manually by the user.
BASE_FEATURE(kDesktopPWAsPreventClose,
#if BUILDFLAG(IS_CHROMEOS)
             base::FEATURE_ENABLED_BY_DEFAULT
#else
             base::FEATURE_DISABLED_BY_DEFAULT
#endif
);

// Adds a user settings that allows PWAs to be opened with a tab strip.
BASE_FEATURE(kDesktopPWAsTabStripSettings, base::FEATURE_DISABLED_BY_DEFAULT);

// Removes the Window Controls Overlay toggle button from the PWA toolbar
// and auto-enables WCO when the app developer specifies it in the manifest.
// When disabled, the toggle button is shown and WCO must be enabled by the
// user. This feature only affects apps that have "window-controls-overlay" in
// their PWA manifest's display_override field, apps without manifest support
// are unaffected.
BASE_FEATURE(kDesktopPWAsWindowControlsOverlayWithNoToggle,
             base::FEATURE_DISABLED_BY_DEFAULT);

// Enables the standalone Document Picture-in-Picture window path, replacing
// the Browser-backed implementation with a dedicated host.
BASE_FEATURE(kDocumentPipStandaloneWindow, base::FEATURE_DISABLED_BY_DEFAULT);

// Allows fullscreen to claim whole display area when in windowing mode
#if BUILDFLAG(IS_ANDROID)
BASE_FEATURE(kDisplayEdgeToEdgeFullscreen, base::FEATURE_ENABLED_BY_DEFAULT);
#endif

// Enables Fullscreen to Screen on Android platform
#if BUILDFLAG(IS_ANDROID)
BASE_FEATURE(kEnableFullscreenToAnyScreenAndroid,
             base::FEATURE_DISABLED_BY_DEFAULT);
#endif

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
// Controls whether Chrome Apps are supported. See https://crbug.com/40186761.
// If the feature is disabled, Chrome Apps continue to work. If enabled, Chrome
// Apps will not launch and will be marked in the UI as deprecated.
BASE_FEATURE(kChromeAppsDeprecation, base::FEATURE_ENABLED_BY_DEFAULT);
#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)

#if BUILDFLAG(IS_CHROMEOS)

BASE_FEATURE(kForcedAppRelaunchOnPlaceholderUpdate,
             base::FEATURE_ENABLED_BY_DEFAULT);
#endif  // BUILDFLAG(IS_CHROMEOS)

// Controls whether the actor component of Glic is enabled.
BASE_FEATURE(kGlicActor, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicActorApcComparison, base::FEATURE_ENABLED_BY_DEFAULT);

const base::FeatureParam<double> kGlicActorApcComparisonSamplingRate{
    &kGlicActorApcComparison, "sampling-rate", 0.1};

BASE_FEATURE(kGlicIgnoreDogfoodClient, base::FEATURE_DISABLED_BY_DEFAULT);

BASE_FEATURE(kGlicExperimentalTriggering, base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kGlicExperimentalTriggeringOptInTabFocus,
             base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kGlicExperimentalTriggeringScreenshot,
             base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kGlicExperimentalTriggeringSuppressDoneNotification,
             base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kGlicExperimentalTriggeringOptInBypass,
             base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kGlicExperimentalTriggeringOpenWindowIfNone,
             base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kGlicBackgroundTriggering, base::FEATURE_DISABLED_BY_DEFAULT);

const base::FeatureParam<std::string> kGlicExperimentalTriggeringOptInURL{
    &kGlicExperimentalTriggering, "glic-experimental-triggering-opt-in-url",
    "https://gemini.google.com/glic/intro?"};

const base::FeatureParam<std::string> kGlicExperimentalTriggeringTabFocusHosts{
    &kGlicExperimentalTriggeringOptInTabFocus,
    "glic-experimental-triggering-tab-focus-hosts",
    "gemini.google.com,gemini-autopush.corp.google.com"};

const base::FeatureParam<std::string>
    kGlicExperimentalTriggeringTabFocusPathSubstring{
        &kGlicExperimentalTriggeringOptInTabFocus,
        "glic-experimental-triggering-tab-focus-path-substring",
        "/spark,/corp/spark"};

const base::FeatureParam<std::string>
    kGlicExperimentalTriggeringTabFocusFallbackURL{
        &kGlicExperimentalTriggeringOptInTabFocus,
        "glic-experimental-triggering-tab-focus-fallback-url",
        "https://gemini.google.com/spark"};

const base::FeatureParam<base::TimeDelta> kGlicActorPageToolTimeout{
    &kGlicActor, "glic-actor-page-tool-timeout", base::Seconds(30)};

const base::FeatureParam<base::TimeDelta> kGlicActorClickDelay{
    &kGlicActor, "glic-actor-click-delay", base::Milliseconds(5)};

// Controls whether the Actor UI components are enabled.
BASE_FEATURE(kGlicActorUi, base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kGlicConfirmTabClose, base::FEATURE_ENABLED_BY_DEFAULT);
// Controls whether we ignore users preference of reduced motion enabled and
// still show the tab indicator spinner. No-op if kGlicActorUiTabIndicator is
// disabled.
BASE_FEATURE(kGlicActorUiTabIndicatorSpinnerIgnoreReducedMotion,
             base::FEATURE_ENABLED_BY_DEFAULT);

// Controls theming updates for Actor UI, including the tab indicator spinner
// and other elements.
BASE_FEATURE(kActorUiThemed, base::FEATURE_ENABLED_BY_DEFAULT);

// Controls whether UI bug fixes for the Task Icon are enabled.
BASE_FEATURE(kGlicActorUiTaskIconUiFixes, base::FEATURE_ENABLED_BY_DEFAULT);

// If enabled, delays showing the Actor task list bubble to allow layout
// animations to settle.
BASE_FEATURE(kGlicActorUiTaskListBubbleDelayShow,
             base::FEATURE_ENABLED_BY_DEFAULT);

const base::FeatureParam<int> kGlicActorUiTaskListBubbleDelayMs{
    &kGlicActorUiTaskListBubbleDelayShow, "delay_ms", 250};

// If enabled, post tasks in the window controller to fix re-entrancy crash.
BASE_FEATURE(kGlicActorPostTaskUiUpdateEnabled,
             base::FEATURE_ENABLED_BY_DEFAULT);

// If enabled, shows handoff button in immersive mode.
BASE_FEATURE(kGlicHandoffButtonShowInImmersiveMode,
             base::FEATURE_ENABLED_BY_DEFAULT);

// If enabled, reset handoff button focus and hover state on button close.
BASE_FEATURE(kGlicHandoffButtonResetFocusAndHoverStatus,
             base::FEATURE_ENABLED_BY_DEFAULT);

// If enabled, hide handoff button when omnibox popup is opened.
BASE_FEATURE(kGlicHandoffButtonHideWhenOmniboxPopupOpened,
             base::FEATURE_ENABLED_BY_DEFAULT);

// If enabled, hide handoff button when tab modal UI is shown.
BASE_FEATURE(kGlicHandoffButtonHideWhenModalUIShown,
             base::FEATURE_ENABLED_BY_DEFAULT);

// If enabled, the magic cursor is shown during actuation for mouse movements
// and clicks.
BASE_FEATURE(kGlicActorUiMagicCursor, base::FEATURE_ENABLED_BY_DEFAULT);

// Default: 1.5 pixels per millisecond
const base::FeatureParam<double> kGlicActorUiMagicCursorSpeed{
    &kGlicActorUiMagicCursor, "magic-cursor-speed-px-per-ms", 1.5};

// Default: 50ms
const base::FeatureParam<int> kGlicActorUiMagicCursorMinDuration{
    &kGlicActorUiMagicCursor, "magic-cursor-min-duration-ms", 50};

// Default: 300ms
const base::FeatureParam<int> kGlicActorUiMagicCursorMaxDuration{
    &kGlicActorUiMagicCursor, "magic-cursor-max-duration-ms", 300};

// If enabled, tool execution is split into separate Validate and Execute steps.
// The Validate step initializes the tool in the renderer and returns the
// target's coordinate point early, before the actual execution occurs.
BASE_FEATURE(kGlicActorSplitValidateAndExecute,
             base::FEATURE_ENABLED_BY_DEFAULT);

const char kGlicActorUiTaskIconName[] = "glic-actor-ui-task-icon";
const char kGlicActorUiOverlayName[] = "glic-actor-ui-overlay";
const char kGlicActorUiToastName[] = "glic-actor-ui-toast";
const char kGlicActorUiHandoffButtonName[] = "glic-actor-ui-handoff-button";
const char kGlicActorUiTabIndicatorName[] = "glic-actor-ui-tab-indicator";
const char kGlicActorUiBorderGlowName[] = "glic-actor-ui-border-glow";
const char kGlicActorUiDebounceTimerName[] = "glic-actor-ui-debounce-timer";

// Controls whether the task icon in the actor ui is enabled.
const base::FeatureParam<bool> kGlicActorUiTaskIcon{
    &kGlicActorUi, kGlicActorUiTaskIconName, true};
// Controls whether the Actor Overlay in the actor ui is enabled.
const base::FeatureParam<bool> kGlicActorUiOverlay{
    &kGlicActorUi, kGlicActorUiOverlayName, true};
// Controls whether the toast in the actor ui is enabled.
const base::FeatureParam<bool> kGlicActorUiToast{&kGlicActorUi,
                                                 kGlicActorUiToastName, true};
// Controls whether the handoff button in the actor ui is enabled.
const base::FeatureParam<bool> kGlicActorUiHandoffButton{
    &kGlicActorUi, kGlicActorUiHandoffButtonName, true};
// Controls whether the tab indicator in the actor ui is enabled.
const base::FeatureParam<bool> kGlicActorUiTabIndicator{
    &kGlicActorUi, kGlicActorUiTabIndicatorName, true};
// Controls whether the actor border glow in the actor ui is enabled.
const base::FeatureParam<bool> kGlicActorUiBorderGlow{
    &kGlicActorUi, kGlicActorUiBorderGlowName, true};
// Controls the debounce timer for the Glic Actor UI Tab Controller, in
// milliseconds. This is used to debounce hover events on the actor overlay and
// handoff button.
const base::FeatureParam<base::TimeDelta> kGlicActorUiDebounceTimer{
    &kGlicActorUi, kGlicActorUiDebounceTimerName, base::Milliseconds(25)};

const base::FeatureParam<int> kGlicActorUiCompletedTaskExpiryDelaySeconds{
    &kGlicActorUi, "glic-actor-ui-completed-task-expiry-delay", 30};

// The overall observation timeout when waiting on a renderer tool to complete.
const base::FeatureParam<base::TimeDelta> kGlicActorPageStabilityTimeout{
    &kGlicActor, "glic-actor-page-stability-timeout", base::Seconds(4)};

// The minimum amount of time to wait for page stability before invoking the
// callback.
const base::FeatureParam<base::TimeDelta> kGlicActorPageStabilityMinWait{
    &kGlicActor, "glic-actor-page-stability-min-wait", base::Seconds(1)};

// The overall observation timeout when waiting for a tool to complete.
// This timeout is long but based on the NavigationToLoadEventFired UMA. This
// should be tuned with real world usage.
const base::FeatureParam<base::TimeDelta> kActorObservationDelayTimeout{
    &kGlicActor, "actor-observation-delay-timeout", base::Seconds(10)};

// The additional delay before completing a tool if LCP is not detected yet upon
// loading.
const base::FeatureParam<base::TimeDelta> kActorObservationDelayLcp{
    &kGlicActor, "actor-observation-delay-lcp", base::Seconds(1)};

// The time for Autofill to parse and classify form fields.
// Autofill is expected to return within this timeout (having successfully
// parsed the form fields or not).
// LINT.IfChange(kActorObservationDelayAutofillPredictionsTimeout)
BASE_FEATURE_PARAM(base::TimeDelta,
                   kActorObservationDelayAutofillPredictionsTimeout,
                   &kGlicActor,
                   "actor-observation-delay-autofill-predictions-timeout",
                   base::Seconds(1));
// LINT.ThenChange(//ios/chrome/browser/intelligence/features/features.mm:kActorPageStabilityAutofillPredictionsTimeout)

// If enabled, observation for page load excludes load in ad frames.
BASE_FEATURE(kGlicActorObservationDelayExcludeAdFrameLoading,
             base::FEATURE_DISABLED_BY_DEFAULT);

// Controls whether typing happens incrementally.
BASE_FEATURE(kGlicActorIncrementalTyping, base::FEATURE_ENABLED_BY_DEFAULT);

const base::FeatureParam<base::TimeDelta> kGlicActorKeyDownDuration{
    &kGlicActorIncrementalTyping,
    "glic-actor-incremental-typing-key-down-duration", base::Milliseconds(25)};

const base::FeatureParam<base::TimeDelta> kGlicActorKeyUpDuration{
    &kGlicActorIncrementalTyping,
    "glic-actor-incremental-typing-key-up-duration", base::Milliseconds(25)};

// For long text (as defined by the threshold below), this multiplier will be
// applied to the delays above to change typing speed.
const base::FeatureParam<double> kGlicActorIncrementalTypingLongMultiplier{
    &kGlicActorIncrementalTyping,
    "glic-actor-incremental-typing-long-multiplier", 0.2};

// When incremental typing is enabled, controls the number of characters at
// which a string to type is considered long (and thus speed boosted).
const base::FeatureParam<size_t> kGlicActorIncrementalTypingLongTextThreshold{
    &kGlicActorIncrementalTyping,
    "glic-actor-incremental-typing-long-text-threshold", 45};

// When incremental typing is enabled, for even longer text (as defined by this
// threshold), directly paste the text instead of simulate typing.
const base::FeatureParam<size_t>
    kGlicActorIncrementalTypingLongTextPasteThreshold{
        &kGlicActorIncrementalTyping, "glic-actor-long-text-paste-threshold",
        200};

// Whether to wait for an editable element before starts typing.
const base::FeatureParam<bool>
    kGlicActorIncrementalTypingWaitForEditableElement{
        &kGlicActorIncrementalTyping,
        "glic-actor-incremental-typing-wait-for-editable-element", true};

// Whether to clear auto-selection when typing subsequent characters.
const base::FeatureParam<bool> kGlicActorIncrementalTypingClearAutoSelection{
    &kGlicActorIncrementalTyping,
    "glic-actor-incremental-typing-clear-auto-selection", false};

// If the TypeTool is invoked with followed_by_enter, the enter key is
// dispatched with this delay.
const base::FeatureParam<base::TimeDelta> kGlicActorTypeToolEnterDelay{
    &kGlicActor, "glic-actor-type-tool-enter-delay", base::Milliseconds(600)};

constexpr base::FeatureParam<std::string> kGlicActorEligibleTiers{
    &kGlicActor, "glic-actor-eligible-tiers", "1,2"};

constexpr base::FeatureParam<GlicActorEnterprisePrefDefault>::Option
    kGlicActorEnterprisePrefDefaultOptions[] = {
        {GlicActorEnterprisePrefDefault::kEnabledByDefault,
         "enabled_by_default"},
        {GlicActorEnterprisePrefDefault::kDisabledByDefault,
         "disabled_by_default"},
        {GlicActorEnterprisePrefDefault::kForcedDisabled, "forced_disabled"},
};

BASE_FEATURE_ENUM_PARAM(GlicActorEnterprisePrefDefault,
                        kGlicActorEnterprisePrefDefault,
                        &kGlicActor,
                        "glic_actor_enterprise_pref_default",
                        GlicActorEnterprisePrefDefault::kDisabledByDefault,
                        &kGlicActorEnterprisePrefDefaultOptions);

const base::FeatureParam<bool> kGlicActorPolicyControlExemption{
    &kGlicActor, "glic_actor_policy_control_exemption", false};

BASE_FEATURE(kGlicActorWorkspaceExemptFromTierCheckRegressionFixKillswitch,
             base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicActorPermissionsBypass, base::FEATURE_DISABLED_BY_DEFAULT);

// Enables rejecting actor click and type targets when Blink reports a
// non-disabled, non-ARIA interaction-disallowed state. Disabled controls are
// always rejected.
BASE_FEATURE(kGlicActorRejectInteractionDisallowedTargets,
             base::FEATURE_DISABLED_BY_DEFAULT);

BASE_FEATURE(kGlicActorToctouValidation, base::FEATURE_DISABLED_BY_DEFAULT);

// Allows normal DOM-ID clicks on targets with no non-empty client rects by
// using an unoccluded visible descendant as the interaction point.
BASE_FEATURE(kGlicActorDomIdClicksOnZeroAreaTargets,
             base::FEATURE_ENABLED_BY_DEFAULT);

// Enables the explicit actor path that directly activates an observed DOM node
// when its interaction point is covered by an eligible modeless panel.
BASE_FEATURE(kGlicActorOccludedDirectActivation,
             base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicActorInternalPopups, base::FEATURE_ENABLED_BY_DEFAULT);

// Controls whether the actor framework searches for an interaction point when
// when the center of the target element is obscured.
BASE_FEATURE(kGlicActorIterativeInteractionPointDiscovery,
             base::FEATURE_ENABLED_BY_DEFAULT);
// The maximum number of iterations to search for an interaction point. The
// value 0 means unlimited.
const base::FeatureParam<size_t>
    kGlicActorInterationPointDiscoveryMaxIterations{
        &kGlicActorIterativeInteractionPointDiscovery,
        "interaction-discovery-max-iterations", 1000};

// Whether to trigger mouse move events with each click.
BASE_FEATURE(kGlicActorMoveBeforeClick, base::FEATURE_ENABLED_BY_DEFAULT);

// Delay between move event and click event.
const base::FeatureParam<base::TimeDelta> kGlicActorMoveBeforeClickDelay{
    &kGlicActorMoveBeforeClick, "glic-actor-move-before-click-delay",
    base::Milliseconds(5)};

// Controls country and locale filtering for Glic.
// See chrome/browser/glic/public/glic_enabling.cc for more details.
BASE_FEATURE(kGlicCountryFiltering, base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kGlicUseSessionCountryForFiltering,
             base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kGlicLocaleFiltering, base::FEATURE_ENABLED_BY_DEFAULT);

// Controls the bugfix where the unified FRE synchronizes cookies to the wrong
// storage partition.
BASE_FEATURE(kGlicUseMainPartitionForUnifiedFre,
             base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicMessageFirstFre, base::FEATURE_DISABLED_BY_DEFAULT);

// Controls whether the Glic feature is enabled.
// IMPORTANT: this feature should never be expired! It is used as the main
// kill-switch for Glic and can be used in the future to handle unsupported
// Chrome versions.
BASE_FEATURE(kGlic,
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS) || \
    BUILDFLAG(IS_ANDROID)
             base::FEATURE_ENABLED_BY_DEFAULT
#else
             base::FEATURE_DISABLED_BY_DEFAULT
#endif
);

BASE_FEATURE(kGlicBackgroundActuation, base::FEATURE_DISABLED_BY_DEFAULT);

BASE_FEATURE(kGlicSupportLinks, base::FEATURE_ENABLED_BY_DEFAULT);

const base::FeatureParam<std::string> kGlicLocationMismatchHelpUrl{
    &kGlicSupportLinks, "location_mismatch_help_url",
    "https://support.google.com/gemini/answer/17117411#gic_access"};

const base::FeatureParam<std::string> kGlicIneligibleAccountHelpUrl{
    &kGlicSupportLinks, "ineligible_account_help_url",
    "https://support.google.com/gemini/answer/17117411#gic_access"};

const base::FeatureParam<int> kGlicMinRequiredRamMb{
    &kGlic, "glic-min-required-ram-mb", 0};

const base::FeatureParam<bool> kGlicAdaptiveToolbarAutoPin{
    &kGlic, "adaptive-toolbar-auto-pin", true};

const base::FeatureParam<bool> kGlicBottomSheetPromo{
    &kGlic, "glic-bottom-sheet-promo", false};

// Controls whether the Glic feature uses multiple instances or not.
BASE_FEATURE(kGlicMultiInstance, base::FEATURE_ENABLED_BY_DEFAULT);

// Glic WebContentsWarming is now always enabled. This feature is kept around
// for now to allow configuring params.
BASE_FEATURE(kGlicWebContentsWarming, base::FEATURE_ENABLED_BY_DEFAULT);

// Controls the delay before the WebContents is warmed. A large delay will
// effectively turn off warming.
const base::FeatureParam<base::TimeDelta> kGlicWebContentsWarmingDelay{
    &kGlicWebContentsWarming, "glic-web-contents-warming-delay",
    base::Seconds(20)};
// Controls the delay before the WebContents is removed from the pool if it is
// not used.
const base::FeatureParam<base::TimeDelta>
    kGlicWebContentsWarmingPoolExpiryDelay{
        &kGlicWebContentsWarming, "glic-web-contents-warming-pool-expiry-delay",
        base::Hours(23)};

// Controls desired min width for the side panel. Not guaranteed to be respected
// if user manually resizes.
const base::FeatureParam<int> kGlicSidePanelMinWidth{
    &kGlicMultiInstance, "glic-side-panel-min-width", 384};
// Controls the width and height of the multi-instance floating panel.
const base::FeatureParam<int> kGlicMultiInstanceFloatyWidth{
    &kGlicMultiInstance, "glic-multi-instance-floaty-width", 400};
const base::FeatureParam<int> kGlicMultiInstanceFloatyHeight{
    &kGlicMultiInstance, "glic-multi-instance-floaty-height", 400};

// Controls whether the Glic feature's z order changes based on the webclient
// mode.
BASE_FEATURE(kGlicZOrderChanges, base::FEATURE_DISABLED_BY_DEFAULT);

// Whether to sync @google.com account cookies. This is only for development and
// testing.
BASE_FEATURE(kGlicDevelopmentSyncGoogleCookies,
             "GlicDevelopmentCookies",
             base::FEATURE_DISABLED_BY_DEFAULT);

// When this feature is enabled, device bound sessions in the Glic storage
// partition are cleared in addition to cookies. This prevents DBSC deferrals.
BASE_FEATURE(kGlicClearDeviceBoundSessionsOnFirstSync,
             base::FEATURE_ENABLED_BY_DEFAULT);

const base::FeatureParam<bool> kGlicStatusIconOpenMenuWithSecondaryClick{
    &kGlic, "open-status-icon-menu-with-secondary-click", true};

// Controls whether the simplified version of the border should be used.
BASE_FEATURE(kGlicForceSimplifiedBorder, base::FEATURE_DISABLED_BY_DEFAULT);

// Controls whether to use a simplified version of the border that does not use
// cc::PaintShader::MakeSkSLCommand.
BASE_FEATURE(kGlicForceNonSkSLBorder, base::FEATURE_DISABLED_BY_DEFAULT);

const base::FeatureParam<int> kGlicInitialWidth{&kGlic, "glic-initial-width",
                                                352};
const base::FeatureParam<int> kGlicInitialHeight{&kGlic, "glic-initial-height",
                                                 86};

// Quality value in the range [0, 100]. For use with gfx::JPEGCodec::Encode().
const base::FeatureParam<int> kGlicScreenshotEncodeQuality{
    &kGlic, "glic-screenshot-encode-quality", 100};

const base::FeatureParam<std::string> kGlicDefaultHotkey{
    &kGlic, "glic-default-hotkey", ""};

BASE_FEATURE(kGlicURLConfig, base::FEATURE_ENABLED_BY_DEFAULT);
const base::FeatureParam<std::string> kGlicGuestURL{
    &kGlicURLConfig, "glic-guest-url", "https://gemini.google.com/glic"};

BASE_FEATURE_PARAM(std::string,
                   kGlicUserStatusUrl,
                   &kGlicUserStatusCheck,
                   "glic-user-status-url",
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
                   "https://geminiweb-pa.googleapis.com/v1/glicStatus"
#else
                   ""
#endif
);

BASE_FEATURE_PARAM(base::TimeDelta,
                   kGlicUserStatusRequestDelay,
                   &kGlicUserStatusCheck,
                   "glic-user-status-request-delay",
                   base::Hours(23));

BASE_FEATURE_PARAM(std::string,
                   kGeminiOAuth2Scope,
                   &kGlicUserStatusCheck,
                   "glic-user-status-oauth2-scope",
                   "https://www.googleapis.com/auth/gemini");

BASE_FEATURE_PARAM(double,
                   kGlicUserStatusRequestDelayJitter,
                   &kGlicUserStatusCheck,
                   "glic-user-status-request-delay-jitter",
                   0.005);

constexpr base::FeatureParam<GlicEnterpriseCheckStrategy>::Option
    kGlicEnterpriseCheckStrategyOptions[] = {
        {GlicEnterpriseCheckStrategy::kPolicy, "policy"},
        {GlicEnterpriseCheckStrategy::kManaged, "managed"},
};
BASE_FEATURE_ENUM_PARAM(GlicEnterpriseCheckStrategy,
                        kGlicUserStatusEnterpriseCheckStrategy,
                        &kGlicUserStatusCheck,
                        "glic-user-status-enterprise-check-strategy",
                        GlicEnterpriseCheckStrategy::kManaged,
                        &kGlicEnterpriseCheckStrategyOptions);

// When true, the Glic API exposes a method to propose refreshing the
// user status.
BASE_FEATURE_PARAM(bool,
                   kGlicUserStatusRefreshApi,
                   &kGlicUserStatusCheck,
                   "glic-user-status-refresh-api",
                   true);

// The minimum time between user status update requests, when triggered by
// the Glic API (or another reason that might occur frequently).
BASE_FEATURE_PARAM(base::TimeDelta,
                   kGlicUserStatusThrottleInterval,
                   &kGlicUserStatusCheck,
                   "glic-user-status-throttle-interval",
                   base::Seconds(5));

BASE_FEATURE(kGlicLearnMoreURLConfig, base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE_PARAM(std::string,
                   kGlicShortcutsLearnMoreURL,
                   &kGlicLearnMoreURLConfig,
                   "glic-shortcuts-learn-more-url",
                   "https://support.google.com/gemini?p=chrome_ks");
BASE_FEATURE_PARAM(std::string,
                   kGlicLauncherToggleLearnMoreURL,
                   &kGlicLearnMoreURLConfig,
                   "glic-shortcuts-launcher-toggle-learn-more-url",
                   "https://support.google.com/gemini?p=chrome_min");
BASE_FEATURE_PARAM(
    std::string,
    kGlicLocationToggleLearnMoreURL,
    &kGlicLearnMoreURLConfig,
    "glic-shortcuts-location-toggle-learn-more-url",
    "https://support.google.com/gemini/answer/"
    "13594961?hl=en#location_info&zippy=%2Cwhat-location-information-do-gemini-"
    "apps-collect-why-and-how-is-it-used");
BASE_FEATURE_PARAM(std::string,
                   kGlicTabAccessToggleLearnMoreURL,
                   &kGlicLearnMoreURLConfig,
                   "glic-shortcuts-tab-access-toggle-learn-more-url",
                   "https://support.google.com/gemini?p=chrome_PH");
BASE_FEATURE_PARAM(
    std::string,
    kGlicTabAccessToggleLearnMoreURLDataProtected,
    &kGlicLearnMoreURLConfig,
    "glic-shortcuts-tab-access-toggle-learn-more-url-data-protected",
    "https://support.google.com/a/answer/15706919");
BASE_FEATURE_PARAM(std::string,
                   kGlicDefaultTabAccessToggleLearnMoreURL,
                   &kGlicLearnMoreURLConfig,
                   "glic-default-tab-access-toggle-learn-more-url",
                   "https://support.google.com/gemini/answer/"
                   "13594961?hl=en#chrome&zippy=%2Cwhat-happens-to-my-data-"
                   "when-i-use-gemini-in-chrome");
BASE_FEATURE_PARAM(
    std::string,
    kGlicDefaultTabAccessToggleLearnMoreURLDataProtected,
    &kGlicLearnMoreURLConfig,
    "glic-default-tab-access-toggle-learn-more-url-data-protected",
    "https://support.google.com/a/answer/15706919");
BASE_FEATURE_PARAM(std::string,
                   kGlicSettingsPageLearnMoreURL,
                   &kGlicLearnMoreURLConfig,
                   "glic-settings-page-learn-more-url",
                   "");
BASE_FEATURE_PARAM(std::string,
                   kGlicWebActuationToggleLearnMoreURL,
                   &kGlicLearnMoreURLConfig,
                   "glic-actuation-on-web-toggle-learn-more-url",
                   "https://support.google.com/gemini?p=gic_agent");
BASE_FEATURE_PARAM(std::string,
                   kGlicExperimentalTriggeringLearnMoreURL,
                   &kGlicLearnMoreURLConfig,
                   "glic-experimental-triggering-toggle-learn-more-url",
                   "https://support.google.com/chrome?p=gemini_spark");
BASE_FEATURE_PARAM(std::string,
                   kGlicExperimentalTriggeringSafetyURL,
                   &kGlicLearnMoreURLConfig,
                   "glic-experimental-triggering-toggle-safety-url",
                   "https://support.google.com/chrome?p=gemini_spark_safety");
// These URLs are passed to settings UI templates.
// Note: Settings WebUI (glic_subpage.ts) matches these links by substring
// ("use-policy" and "unexpected_results") to apply accessibility labels.
// Finch configurations overriding these URLs should retain these substrings
// or update the WebUI logic accordingly.
BASE_FEATURE_PARAM(
    std::string,
    kGlicWebActuationToggleConsiderSafelyURL,
    &kGlicLearnMoreURLConfig,
    "glic-actuation-on-web-toggle-things-to-consider-safely-url",
    "https://policies.google.com/terms/generative-ai/use-policy");
BASE_FEATURE_PARAM(
    std::string,
    kGlicWebActuationToggleConsiderUnexpectedResultsURL,
    &kGlicLearnMoreURLConfig,
    "glic-actuation-on-web-toggle-things-to-consider-unexpected-results-url",
    "https://support.google.com/gemini?p=gic_unexpected_results");
BASE_FEATURE_PARAM(std::string,
                   kGlicExtensionsManagementUrl,
                   &kGlicLearnMoreURLConfig,
                   "glic-extensions-management-url",
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
                   "https://gemini.google.com/apps"
#else
                   ""
#endif
);

BASE_FEATURE(kGlicCSPConfig, base::FEATURE_ENABLED_BY_DEFAULT);
const base::FeatureParam<std::string> kGlicAllowedOriginsOverride{
    &kGlicCSPConfig, "glic-allowed-origins-override",
    // Space-delimited set of allowed origins.
    "https://gemini.google.com https://www.google.com"};
// Origins that can use the Glic API. The default Glic guest origin is
// automatically allowed, this restricts API use if the guest navigates.
const base::FeatureParam<std::string> kGlicApiAllowedOrigins{
    &kGlicCSPConfig, "glic-api-allowed-origins",
    // Space-delimited set of origins allowed to have API access.
    "https://gemini.google.com "
    "https://gemini.corp.google.com "
    "https://gemini-autopush.corp.google.com "
    "https://gemini-staging.corp.google.com "
    "https://gemini-preprod.corp.google.com"};

// Enable/disable Glic web client responsiveness check feature.
BASE_FEATURE(kGlicClientResponsivenessCheck, base::FEATURE_ENABLED_BY_DEFAULT);
// TODO(crbug.com/402184931): Set appropriate default for the 3 following
// parameters.
// Time interval for periodically sending responsiveness check to the web client
// in milliseconds.
const base::FeatureParam<int> kGlicClientResponsivenessCheckIntervalMs{
    &kGlicClientResponsivenessCheck,
    "glic-client-responsiveness-check-interval-ms", 5000};
// Maximum time to wait for glicWebClientCheckResponsive response during a
// responsiveness check before flagging the web client as unresponsive.
const base::FeatureParam<int> kGlicClientResponsivenessCheckTimeoutMs{
    &kGlicClientResponsivenessCheck,
    "glic-client-responsiveness-check-timeout-ms", 500};
// Maximum time for showing client unresponsive UI before going to the error
// state.
const base::FeatureParam<int> kGlicClientUnresponsiveUiMaxTimeMs{
    &kGlicClientResponsivenessCheck, "glic-client-unresponsive-ui-max-time-ms",
    5000};
// When true, the responsiveness check will be ignored when the debugger is
// attached to the webview.
const base::FeatureParam<bool>
    kGlicClientResponsivenessCheckIgnoreWhenDebuggerAttached{
        &kGlicClientResponsivenessCheck,
        "glic-client-responsiveness-check-ignore-when-debugger-attached", true};

BASE_FEATURE(kGlicEnableCachedGetUserProfileInfo,
             base::FEATURE_DISABLED_BY_DEFAULT);

BASE_FEATURE(kGlicUseShaderCache, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicDragAndDropFileUpload, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicKeyboardShortcutNewBadge, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicAppMenuNewBadge, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicDebugWebview, base::FEATURE_DISABLED_BY_DEFAULT);

BASE_FEATURE(kGlicScrollTo, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicCaptureRegion, base::FEATURE_ENABLED_BY_DEFAULT);

// Controls whether we enforce that documentId (an optional parameter) is set
// when trying to scroll all documents except PDFs (and fail the request if
// it's not set).
const base::FeatureParam<bool> kGlicScrollToEnforceDocumentId{
    &kGlicScrollTo, "glic-scroll-to-enforce-document-id", true};
// Expand the scrollTo capability to PDF documents.
const base::FeatureParam<bool> kGlicScrollToPDF{&kGlicScrollTo,
                                                "glic-scroll-to-pdf", false};
// Controls whether we enforce that url (an optional parameter) is set when
// trying to scroll a PDF document (and fail the request if it's not set).
const base::FeatureParam<bool> kGlicScrollToEnforceURLForPDF{
    &kGlicScrollTo, "glic-scroll-to-enforce-url-for-pdf", true};

BASE_FEATURE(kGlicWarming, base::FEATURE_DISABLED_BY_DEFAULT);

// Controls the amount of time from the GlicButtonController scheduling
// preload to the start of preloading (if preloading is possible).
const base::FeatureParam<int> kGlicWarmingDelayMs{
    &kGlicWarming, "glic-warming-delay-ms", 20 * 1000};

// Adds noise to the warming delay. The effective delay is increased by a
// random positive number of milliseconds between 0 and kGlicWarmingJitterMs.
const base::FeatureParam<int> kGlicWarmingJitterMs{
    &kGlicWarming, "glic-warming-jitter-ms", 10 * 1000};

// Blocks prewarming if the device has less than this amount of physical memory.
// If 0, memory is not checked.
const base::FeatureParam<size_t> kGlicWarmingMinRequiredRamMb{
    &kGlicWarming, "glic-warming-min-required-ram-mb", 0};

BASE_FEATURE(kGlicTieredRollout, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicRollout, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicUserStatusCheck, base::FEATURE_ENABLED_BY_DEFAULT);

// When enabled, if GlicUserStatusFetcher receives an error when checking for
// managed status, and the refresh token is missing, it will retry. This fixes
// a race condition on sign-in.
BASE_FEATURE(kGlicUserStatusHandlesRefreshTokenLoss,
             base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicDefaultTabContextSetting, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicDefaultContextPinOnBind, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicUnloadOnClose, base::FEATURE_DISABLED_BY_DEFAULT);

BASE_FEATURE(kGlicBindPinnedUnboundTab, base::FEATURE_ENABLED_BY_DEFAULT);

// When enabled, don't try to update the views background color based on the
// glic client background color.
BASE_FEATURE(kGlicExplicitBackgroundColor, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicPersonalContext, base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kGlicGeminiInstructions, base::FEATURE_DISABLED_BY_DEFAULT);

BASE_FEATURE(kGlicPopupWindowsEnabled, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicRecordActorJournal, base::FEATURE_ENABLED_BY_DEFAULT);
extern const base::FeatureParam<int> kGlicRecordActorJournalFeedbackProductId{
    &kGlicRecordActorJournal, "glic-record-actor-journal-feedback-product-id",
    5320395};
extern const base::FeatureParam<std::string>
    kGlicRecordActorJournalFeedbackCategoryTag{
        &kGlicRecordActorJournal,
        "glic-record-actor-journal-feedback-category-tag",
        "gemini_in_chrome_actor_tt_df"};

BASE_FEATURE(kGlicRecordMemoryFootprintMetrics,
             base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicRegionSelectionLine, base::FEATURE_DISABLED_BY_DEFAULT);

BASE_FEATURE(kGlicWebClientUnresponsiveMetrics,
             base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicParameterizedShader, base::FEATURE_ENABLED_BY_DEFAULT);
extern const base::FeatureParam<std::string> kGlicParameterizedShaderColors{
    &kGlicParameterizedShader, "glic-parameterized-shader-colors",
    "#3186FF#346BF1#4FA0FF#FF4641#FFCC00#0EBC5F"};
extern const base::FeatureParam<std::string> kGlicParameterizedShaderFloats{
    &kGlicParameterizedShader, "glic-parameterized-shader-floats",
    "5#0.1#0.3#0.7#1.0#0.5#0.5#0.3"};

BASE_FEATURE(kGlicTabFocusDataDedupDebounce, base::FEATURE_ENABLED_BY_DEFAULT);
const base::FeatureParam<int> kGlicTabFocusDataDebounceDelayMs{
    &kGlicTabFocusDataDedupDebounce, "glic-tab-focus-data-debounce-delay-ms",
    5};
const base::FeatureParam<int> kGlicTabFocusDataMaxDebounces{
    &kGlicTabFocusDataDedupDebounce, "glic-tab-focus-data-max-debounces", 5};

// Kill switch for getTabById API.
BASE_FEATURE(kGlicGetTabByIdApi, base::FEATURE_ENABLED_BY_DEFAULT);
// Kill switch for openPasswordManagerSettingsPage API.
BASE_FEATURE(kGlicOpenPasswordManagerSettingsPageApi,
             base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicAssetsV2, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicFaviconDataUrls, base::FEATURE_DISABLED_BY_DEFAULT);

// Whether Glic should ignore the offline network status, and assume it is
// online.
BASE_FEATURE(kGlicIgnoreOfflineState, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicExtensions, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicMultitabUnderlines, base::FEATURE_ENABLED_BY_DEFAULT);

// When enabled, the X-Glic headers will be attached to requests as specified by
// the kGlicHeaderRequestTypes param.
BASE_FEATURE(kGlicHeader, base::FEATURE_ENABLED_BY_DEFAULT);

// Comma-separated list of request types to attach the X-Glic headers to.
// These must be valid values for the webRequest extensions API.
// Previously only "main_frame" was used.
const base::FeatureParam<std::string> kGlicHeaderRequestTypes{
    &kGlicHeader, "glic-header-request-types",
    "main_frame,xmlhttprequest,websocket"};

BASE_FEATURE(kGlicCaaGuestError, base::FEATURE_ENABLED_BY_DEFAULT);
extern const base::FeatureParam<std::string> kGlicCaaLinkUrl{
    &kGlicCaaGuestError, "glic-caa-link-url", "https://gemini.google.com/"};
extern const base::FeatureParam<std::string> kGlicCaaLinkText{
    &kGlicCaaGuestError, "glic-caa-link-text", "gemini.google.com"};
extern const base::FeatureParam<std::string> kGlicCaaGuestRedirectPatterns{
    &kGlicCaaGuestError, "glic-caa-redirect-patterns",
    "https://access.workspace.google.com https://admin.google.com "
    "https://accounts.google.com/info/servicerestricted"};

#if BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_DESKTOP_ANDROID)
BASE_FEATURE(kGlicDaisyChainNewTabs, base::FEATURE_DISABLED_BY_DEFAULT);
#else
BASE_FEATURE(kGlicDaisyChainNewTabs, base::FEATURE_ENABLED_BY_DEFAULT);
#endif

BASE_FEATURE(kGlicLiveModeOnlyGlow, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicGeminiContinueURLRedirect, base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kGlicWebContinuity, base::FEATURE_DISABLED_BY_DEFAULT);
const base::FeatureParam<std::string> kGlicWebContinuityUrl{
    &kGlicWebContinuity, "glic-web-continuity-url", ""};
const base::FeatureParam<std::string> kGlicWebContinuityOriginatingHost{
    &kGlicWebContinuity, "glic-web-continuity-originating-host", ""};
const base::FeatureParam<int> kGlicWebContinuityMaxCIDLength{
    &kGlicWebContinuity, "glic-web-continuity-max-cid-length", 18};
const base::FeatureParam<int> kGlicWebContinuityMaxTargetUrlLength{
    &kGlicWebContinuity, "glic-web-continuity-max-target-url-length", 1024};
const base::FeatureParam<int> kGlicWebContinuityMaxTurnIdLength{
    &kGlicWebContinuity, "glic-web-continuity-max-turn-id-length", 32};

BASE_FEATURE(kGlicUseToolbarHeightSidePanel, base::FEATURE_DISABLED_BY_DEFAULT);

BASE_FEATURE(kGlicButtonPressedState, base::FEATURE_ENABLED_BY_DEFAULT);

const base::FeatureParam<bool> kGlicButtonContainerBackground{
    &kGlicButtonPressedState, "glic-button-container-background", false};
const base::FeatureParam<bool> kGlicButtonPressedForceSolidIcon{
    &kGlicButtonPressedState, "glic-button-pressed-force-solid-icon", true};
const base::FeatureParam<bool> kGlicButtonCustomThemeFallback{
    &kGlicButtonPressedState, "custom-theme-fallback", true};

BASE_FEATURE(kGlicShareImage, base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kGlicShareImageNoNewConversation,
             base::FEATURE_DISABLED_BY_DEFAULT);

BASE_FEATURE(kGlicWebActuationSetting, base::FEATURE_ENABLED_BY_DEFAULT);

const base::FeatureParam<std::string> kGlicWebActuationAllowedTiers{
    &kGlicWebActuationSetting, "allowed_tiers", ""};

// If enabled, show web actuation settings toggle if
// kGlicWebActuationAllowedTiers is populated.
BASE_FEATURE(kGlicWebActuationSettingsToggle,
             base::FEATURE_DISABLED_BY_DEFAULT);

BASE_FEATURE(kGlicSettingsA11yContextFix, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kGlicMetricsSession, base::FEATURE_ENABLED_BY_DEFAULT);
// The duration of inactivity after which a session is considered ended.
const base::FeatureParam<base::TimeDelta> kGlicMetricsSessionInactivityTimeout{
    &kGlicMetricsSession, "glic-metrics-session-inactivity-timeout",
    base::Minutes(45)};
// The duration of being hidden after which a session is considered ended.
const base::FeatureParam<base::TimeDelta> kGlicMetricsSessionHiddenTimeout{
    &kGlicMetricsSession, "glic-metrics-session-hidden-timeout",
    base::Minutes(30)};
// The duration of a transient state change (flicker) that is ignored.
// This must be less than kGlicMetricsSessionHiddenTimeout and
// kGlicMetricsSessionInactivityTimeout.
const base::FeatureParam<base::TimeDelta>
    kGlicMetricsSessionRestartDebounceTimer{
        &kGlicMetricsSession, "glic-metrics-session-restart-debounce-timer",
        base::Seconds(5)};
// The duration of continuous visibility required to start a session.
const base::FeatureParam<base::TimeDelta> kGlicMetricsSessionStartTimeout{
    &kGlicMetricsSession, "glic-metrics-session-start-timeout",
    base::Seconds(5)};

BASE_FEATURE(kGlicPrintMenuItem, base::FEATURE_ENABLED_BY_DEFAULT);

const base::FeatureParam<int> kGlicCompositeViewWidth{
    &kGlicPrintMenuItem, "glic-composite-view-width", 800};

const base::FeatureParam<int> kGlicCompositeViewHeight{
    &kGlicPrintMenuItem, "glic-composite-view-height", 480};

BASE_FEATURE(kGlicArchiveConversation, base::FEATURE_DISABLED_BY_DEFAULT);

// Whether to enable OneTimePassword filling in Glic.
// TODO(b/500683394): Clean up after launch.
BASE_FEATURE(kGlicActorAutofillOneTimePassword,
             base::FEATURE_DISABLED_BY_DEFAULT);

// Whether to click a field before filling it in Glic actor autofill.
// This feature is also gated by |autofill::features::kGlicActorAutofill|.
BASE_FEATURE(kGlicActorAutofillPreClick, base::FEATURE_DISABLED_BY_DEFAULT);

// Whether to enable the section label in Glic actor autofill.
// This feature is also gated by |autofill::features::kGlicActorAutofill|.
BASE_FEATURE(kGlicActorAutofillSectionLabel, base::FEATURE_DISABLED_BY_DEFAULT);

BASE_FEATURE(kGlicGuestUrlPresets, base::FEATURE_DISABLED_BY_DEFAULT);
const base::FeatureParam<int> kGlicGuestUrlPresetType{
    &kGlicGuestUrlPresets, "glic-guest-url-preset-type", 0};

BASE_FEATURE(kGlicContextualCueBubble, base::FEATURE_DISABLED_BY_DEFAULT);



// Enables the `google-chrome://` URI scheme.
BASE_FEATURE(kGoogleChromeScheme, base::FEATURE_ENABLED_BY_DEFAULT);

// Controls whether the Google Search AI Mode Workspace link (Connected Apps) is
// shown in AI Settings. Acts as a killswitch.
BASE_FEATURE(kGoogleSearchAiModeWorkspace, base::FEATURE_ENABLED_BY_DEFAULT);

// Force Privacy Guide to be available even if it would be unavailable
// otherwise. This is meant for development and test purposes only.
BASE_FEATURE(kPrivacyGuideForceAvailable, base::FEATURE_DISABLED_BY_DEFAULT);

#if BUILDFLAG(ENABLE_PDF)
BASE_FEATURE(kPdfGlicSummarize, base::FEATURE_DISABLED_BY_DEFAULT);
const base::FeatureParam<int> kPdfGlicSummarizeArm{&kPdfGlicSummarize, "arm",
                                                   3};
const base::FeatureParam<bool> kPdfGlicSummarizeUseLongButtonText{
    &kPdfGlicSummarize, "use_long_button_text", false};
BASE_FEATURE(kPdfGlicSummarizeFre, base::FEATURE_DISABLED_BY_DEFAULT);
#endif

#if !BUILDFLAG(IS_ANDROID)
// Enables or disables the Happiness Tracking System demo mode for Desktop
// Chrome.
BASE_FEATURE(kHappinessTrackingSurveysForDesktopDemo,
             base::FEATURE_DISABLED_BY_DEFAULT);

BASE_FEATURE(kHappinessTrackingSurveysConfiguration,
             base::FEATURE_ENABLED_BY_DEFAULT);

const base::FeatureParam<std::string> kHappinessTrackingSurveysHostedUrl{
    &kHappinessTrackingSurveysConfiguration, "custom-url",
    "https://www.google.com/chrome/hats/index_m129.html"};

// Enables or disables the Happiness Tracking System for COEP issues in Chrome
// DevTools on Desktop.
BASE_FEATURE(kHaTSDesktopDevToolsIssuesCOEP, base::FEATURE_DISABLED_BY_DEFAULT);

// Enables or disables the Happiness Tracking System for Mixed Content issues in
// Chrome DevTools on Desktop.
BASE_FEATURE(kHaTSDesktopDevToolsIssuesMixedContent,
             base::FEATURE_DISABLED_BY_DEFAULT);

// Enables or disables the Happiness Tracking System for same-site cookies
// issues in Chrome DevTools on Desktop.
BASE_FEATURE(kHappinessTrackingSurveysForDesktopDevToolsIssuesCookiesSameSite,
             base::FEATURE_DISABLED_BY_DEFAULT);

// Enables or disables the Happiness Tracking System for Heavy Ad issues in
// Chrome DevTools on Desktop.
BASE_FEATURE(kHaTSDesktopDevToolsIssuesHeavyAd,
             base::FEATURE_DISABLED_BY_DEFAULT);

// Enables or disables the Happiness Tracking System for CSP issues in Chrome
// DevTools on Desktop.
BASE_FEATURE(kHaTSDesktopDevToolsIssuesCSP, base::FEATURE_DISABLED_BY_DEFAULT);

// Enables or disables the Happiness Tracking System for Desktop Privacy Guide.
BASE_FEATURE(kHappinessTrackingSurveysForDesktopPrivacyGuide,
             base::FEATURE_DISABLED_BY_DEFAULT);
const base::FeatureParam<base::TimeDelta>
    kHappinessTrackingSurveysForDesktopPrivacyGuideTime{
        &kHappinessTrackingSurveysForDesktopPrivacyGuide, "settings-time",
        base::Seconds(20)};

// Enables or disables the Happiness Tracking System for Desktop History Page in
// the Experiment group.
BASE_FEATURE(kHappinessTrackingSurveysForDesktopHistoryPageExperiment,
             base::FEATURE_DISABLED_BY_DEFAULT);
const base::FeatureParam<base::TimeDelta>
    kHappinessTrackingSurveysForDesktopHistoryPageExperimentTime{
        &kHappinessTrackingSurveysForDesktopHistoryPageExperiment,
        "history-page-time", base::Seconds(5)};

// Enables or disables the Happiness Tracking System for Desktop History Page in
// the Control group.
BASE_FEATURE(kHappinessTrackingSurveysForDesktopHistoryPageControl,
             base::FEATURE_DISABLED_BY_DEFAULT);
const base::FeatureParam<base::TimeDelta>
    kHappinessTrackingSurveysForDesktopHistoryPageControlTime{
        &kHappinessTrackingSurveysForDesktopHistoryPageControl,
        "history-page-time", base::Seconds(5)};

// Enables or disables the Happiness Tracking System for Desktop Chrome
// Settings.
BASE_FEATURE(kHappinessTrackingSurveysForDesktopSettings,
             base::FEATURE_DISABLED_BY_DEFAULT);
const base::FeatureParam<base::TimeDelta>
    kHappinessTrackingSurveysForDesktopSettingsTime{
        &kHappinessTrackingSurveysForDesktopSettings, "settings-time",
        base::Seconds(20)};

// Enables or disables the Happiness Tracking System for Desktop Chrome
// Privacy Settings.
BASE_FEATURE(kHappinessTrackingSurveysForDesktopSettingsPrivacy,
             base::FEATURE_DISABLED_BY_DEFAULT);
const base::FeatureParam<bool>
    kHappinessTrackingSurveysForDesktopSettingsPrivacyNoGuide{
        &kHappinessTrackingSurveysForDesktopSettingsPrivacy, "no-guide", false};
const base::FeatureParam<base::TimeDelta>
    kHappinessTrackingSurveysForDesktopSettingsPrivacyTime{
        &kHappinessTrackingSurveysForDesktopSettingsPrivacy, "settings-time",
        base::Seconds(20)};

// Enables or disables the Happiness Tracking System for Desktop Chrome
// NTP Modules.
BASE_FEATURE(kHappinessTrackingSurveysForDesktopNtpModules,
             base::FEATURE_DISABLED_BY_DEFAULT);

// Enables or disables the Happiness Tracking System for Desktop Chrome
// Next Panel.
BASE_FEATURE(kHappinessTrackingSurveysForDesktopNextPanel,
             base::FEATURE_DISABLED_BY_DEFAULT);

// Enables or disables the Happiness Tracking System for History Embeddings.
BASE_FEATURE(kHappinessTrackingSurveysForHistoryEmbeddings,
             base::FEATURE_DISABLED_BY_DEFAULT);
const base::FeatureParam<base::TimeDelta>
    kHappinessTrackingSurveysForHistoryEmbeddingsDelayTime(
        &kHappinessTrackingSurveysForHistoryEmbeddings,
        "HappinessTrackingSurveysForHistoryEmbeddingsDelayTime",
        base::Seconds(20));

BASE_FEATURE(kHappinessTrackingSurveysForNtpPhotosOptOut,
             "HappinessTrackingSurveysForrNtpPhotosOptOut",
             base::FEATURE_DISABLED_BY_DEFAULT);

// Enables or disables the Happiness Tracking System for Wallpaper Search.
BASE_FEATURE(kHappinessTrackingSurveysForWallpaperSearch,
             base::FEATURE_DISABLED_BY_DEFAULT);

// Enables or disables the Happiness Tracking System for Chrome What's New.
BASE_FEATURE(kHappinessTrackingSurveysForDesktopWhatsNew,
             base::FEATURE_ENABLED_BY_DEFAULT);
const base::FeatureParam<base::TimeDelta>
    kHappinessTrackingSurveysForDesktopWhatsNewTime{
        &kHappinessTrackingSurveysForDesktopWhatsNew, "whats-new-time",
        base::Seconds(20)};

// Enables or disables the Happiness Tracking System for SE Hijacking.
BASE_FEATURE(kHappinessTrackingSurveysForDesktopSEHijacking,
             base::FEATURE_DISABLED_BY_DEFAULT);
// Enables or disables the Happiness Tracking System for Chrome security page.
BASE_FEATURE(kHappinessTrackingSurveysForSecurityPage,
             base::FEATURE_DISABLED_BY_DEFAULT);
const base::FeatureParam<base::TimeDelta>
    kHappinessTrackingSurveysForSecurityPageTime{
        &kHappinessTrackingSurveysForSecurityPage, "security-page-time",
        base::Seconds(15)};
const base::FeatureParam<std::string>
    kHappinessTrackingSurveysForSecurityPageTriggerId{
        &kHappinessTrackingSurveysForSecurityPage, "security-page-trigger-id",
        ""};
const base::FeatureParam<bool>
    kHappinessTrackingSurveysForSecurityPageRequireInteraction{
        &kHappinessTrackingSurveysForSecurityPage,
        "security-page-require-interaction", false};
#endif  // !BUILDFLAG(IS_ANDROID)

// Enables HTTPS-First Mode in a balanced configuration that doesn't warn on
// HTTP when HTTPS can't be reasonably expected.
BASE_FEATURE(kHttpsFirstBalancedMode, base::FEATURE_ENABLED_BY_DEFAULT);

// Automatically enables HTTPS-First Mode in a balanced configuration when
// possible.
BASE_FEATURE(kHttpsFirstBalancedModeAutoEnable,
             base::FEATURE_DISABLED_BY_DEFAULT);

// Kill switch for crbug.com/40892208.
BASE_FEATURE(kHttpsFirstModeForAdvancedProtectionUsers,
             "HttpsOnlyModeForAdvancedProtectionUsers",
             base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kHttpsFirstModeDefaultSettingPairsWithEsb,
             base::FEATURE_ENABLED_BY_DEFAULT);

// Enables HTTPS-First Mode for engaged sites. No-op if HttpsFirstModeV2 or
// HTTPS-Upgrades is disabled.
BASE_FEATURE(kHttpsFirstModeV2ForEngagedSites,
             base::FEATURE_ENABLED_BY_DEFAULT);

// Enables HTTPS-First Mode for typically secure users. No-op if
// HttpsFirstModeV2 or HTTPS-Upgrades is disabled.
BASE_FEATURE(kHttpsFirstModeV2ForTypicallySecureUsers,
             base::FEATURE_DISABLED_BY_DEFAULT);

// Enables automatically upgrading main frame navigations to HTTPS.
BASE_FEATURE(kHttpsUpgrades, base::FEATURE_ENABLED_BY_DEFAULT);
// When enabled, typed schemeless navigations (e.g., typed "example.com" in the
// Omnibox) that are upgraded to HTTPS will not fallback to HTTP if the HTTPS
// navigation fails due to a timeout.
BASE_FEATURE(kHttpsUpgradesTypedSchemelessNavigationNoTimeoutFallback,
             base::FEATURE_ENABLED_BY_DEFAULT);

const base::FeatureParam<base::TimeDelta> kHttpsUpgradesFallbackDelay{
    &kHttpsUpgrades, "fallback-delay", base::Seconds(3)};

const base::FeatureParam<base::TimeDelta>
    kHttpsUpgradesAskBeforeHttpFallbackDelay{
        &kHttpsUpgrades, "ask-before-http-fallback-delay", base::Seconds(5)};

// Enables HTTPS-First Mode by default in Incognito Mode.
BASE_FEATURE(kHttpsFirstModeIncognito, base::FEATURE_ENABLED_BY_DEFAULT);

// Enables the Incoming Call Notifications scenario. When created by an
// installed origin, an incoming call notification should have increased
// priority, colored buttons, a ringtone, and a default "close" button.
// Otherwise, if the origin is not installed, it should behave like the default
// notifications, but with the added "Close" button. See
// https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/Notifications/notifications_actions_customization.md
BASE_FEATURE(kIncomingCallNotifications,
#if BUILDFLAG(IS_WIN)
             base::FEATURE_ENABLED_BY_DEFAULT);
#else
             base::FEATURE_DISABLED_BY_DEFAULT);
#endif  // BUILDFLAG(IS_WIN)

// Experimental image replacement feature. b/482792874
BASE_FEATURE(kIndigo, base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kIndigoContextualCueingV2, base::FEATURE_DISABLED_BY_DEFAULT);

const base::FeatureParam<bool> kIndigoRequireGlicEnabling{
    &kIndigo, "indigo_require_glic_enabling", false};
const base::FeatureParam<bool> kIndigoAllowForEnterprise{
    &kIndigo, "allow_indigo_for_enterprise", false};
const base::FeatureParam<bool> kIndigoSkipEnterpriseCheck{
    &kIndigo, "indigo_skip_enterprise_check", false};

const base::FeatureParam<base::TimeDelta> kIndigoAnchoredMessageResetDuration{
    &kIndigo, "indigo_anchored_message_reset_duration", base::Hours(24)};
const base::FeatureParam<std::string> kIndigoGenerateUrl{
    &kIndigo, "indigo_generate_url", ""};
const base::FeatureParam<std::string> kIndigoStatusUrl{&kIndigo,
                                                       "indigo_status_url", ""};
const base::FeatureParam<std::string> kIndigoDeleteUrl{&kIndigo,
                                                       "indigo_delete_url", ""};
const base::FeatureParam<std::string> kIndigoOnboardingUrl{
    &kIndigo, "indigo_onboarding_url", ""};
const base::FeatureParam<std::string> kIndigoSavedUrl{
    &kIndigo, "indigo_saved_url", "about:blank"};
const base::FeatureParam<std::string> kIndigoScopes{
    &kIndigo, "indigo_scopes",
    "https://www.googleapis.com/auth/userinfo.email"};

BASE_FEATURE(kIndigoMetadataKeywordHeuristic,
             base::FEATURE_DISABLED_BY_DEFAULT);
const base::FeatureParam<base::TimeDelta>
    kIndigoMetadataKeywordHeuristicSameDocumentNavigationDelay{
        &kIndigoMetadataKeywordHeuristic,
        "same_document_navigation_metadata_delay", base::Seconds(4)};

// Experimental image replacement feature opens glic.
BASE_FEATURE(kIndigoOpenGlic, base::FEATURE_DISABLED_BY_DEFAULT);
const base::FeatureParam<std::string> kIndigoGlicPrompt{
    &kIndigoOpenGlic, "indigo_glic_prompt", ""};
const base::FeatureParam<std::string> kIndigoGlicPromptKey{
    &kIndigoOpenGlic, "indigo_glic_prompt_key", ""};
const base::FeatureParam<std::string> kIndigoGlicSkillId{
    &kIndigoOpenGlic, "indigo_glic_skill_id", ""};
const base::FeatureParam<base::TimeDelta> kIndigoGlicTriggerDelay{
    &kIndigoOpenGlic, "indigo_glic_trigger_delay", base::Milliseconds(300)};

BASE_FEATURE(kIndigoGeneratedImageCache, base::FEATURE_ENABLED_BY_DEFAULT);
const base::FeatureParam<base::TimeDelta> kIndigoGeneratedImageCacheLifetime{
    &kIndigoGeneratedImageCache, "indigo_generated_image_cache_lifetime",
    base::Minutes(30)};

#if !BUILDFLAG(IS_ANDROID)
// A feature that controls whether Instant uses a spare renderer.
BASE_FEATURE(kInstantUsesSpareRenderer, base::FEATURE_DISABLED_BY_DEFAULT);
#endif  // !BUILDFLAG(IS_ANDROID)

// Enables Isolated Web App Developer Mode, which allows developers to
// install untrusted Isolated Web Apps.
BASE_FEATURE(kIsolatedWebAppDevMode, base::FEATURE_DISABLED_BY_DEFAULT);

// Enables the chrome://iwa-dev WebUI page.
BASE_FEATURE(kIsolatedWebAppDevUi, base::FEATURE_ENABLED_BY_DEFAULT);

// Enables fast update checks for Isolated Web Apps, reducing the update check
// interval to 1 minute.
BASE_FEATURE(kIsolatedWebAppFastUpdateCheck, base::FEATURE_DISABLED_BY_DEFAULT);

// Enables users on unmanaged devices to install Isolated Web Apps.
BASE_FEATURE(kIsolatedWebAppUnmanagedInstall,
#if BUILDFLAG(IS_CHROMEOS)
             base::FEATURE_ENABLED_BY_DEFAULT
#else
             base::FEATURE_DISABLED_BY_DEFAULT
#endif  // BUILDFLAG(IS_CHROMEOS)
);

#if BUILDFLAG(IS_CHROMEOS)
// Enables users to install isolated web apps in managed guest sessions.
BASE_FEATURE(kIsolatedWebAppManagedGuestSessionInstall,
             base::FEATURE_ENABLED_BY_DEFAULT);

// Enables bundle cache for isolated web apps in kiosk and managed guest
// session.
BASE_FEATURE(kIsolatedWebAppBundleCache, base::FEATURE_ENABLED_BY_DEFAULT);
#endif  // BUILDFLAG(IS_CHROMEOS)

#if BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS)
BASE_FEATURE(kLinuxLowMemoryMonitor, base::FEATURE_DISABLED_BY_DEFAULT);
// Values taken from the low-memory-monitor documentation and also apply to the
// portal API:
// https://hadess.pages.freedesktop.org/low-memory-monitor/gdbus-org.freedesktop.LowMemoryMonitor.html
constexpr base::FeatureParam<int> kLinuxLowMemoryMonitorModerateLevel{
    &kLinuxLowMemoryMonitor, "moderate_level", 50};
constexpr base::FeatureParam<int> kLinuxLowMemoryMonitorCriticalLevel{
    &kLinuxLowMemoryMonitor, "critical_level", 255};
#endif  // BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS)

#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
BASE_FEATURE(kListWebAppsSwitch, base::FEATURE_DISABLED_BY_DEFAULT);
#endif

// When enabled, keyed services are instantiated lazily rather than eagerly at
// startup.
BASE_FEATURE(kLazyKeyedServiceInstantiation, base::FEATURE_DISABLED_BY_DEFAULT);

// When enabled, autofill and password manager keyed services are instantiated
// lazily.
BASE_FEATURE_PARAM(bool,
                   kLazyKeyedServiceInstantiationAutofillAndPassword,
                   &features::kLazyKeyedServiceInstantiation,
                   "autofill_and_password",
                   true);

// Enables the use of system notification centers instead of using the Message
// Center for displaying the toasts. The feature is hardcoded to enabled for
// Chrome OS.
BASE_FEATURE(kNativeNotifications, base::FEATURE_ENABLED_BY_DEFAULT);

// Enables installation of the content script for chrome/browser/indigo/ via
// component update.
BASE_FEATURE(kIndigoComponent, base::FEATURE_DISABLED_BY_DEFAULT);
const base::FeatureParam<std::string> kIndigoComponentAttribute{
    &kIndigoComponent, "indigo_component_attribute", ""};

// If enabled, the initial WebUI skips spell check initialization on startup for
// NTP.
BASE_FEATURE(kInitialWebUIWithoutSpellCheckForNtp,
             base::FEATURE_DISABLED_BY_DEFAULT);

BASE_FEATURE(kSystemNotifications, base::FEATURE_ENABLED_BY_DEFAULT);

// When kNoReferrers is enabled, most HTTP requests will provide empty
// referrers instead of their ordinary behavior.
BASE_FEATURE(kNoReferrers, base::FEATURE_DISABLED_BY_DEFAULT);

#if BUILDFLAG(IS_ANDROID)
BASE_FEATURE(kOfflineAutoFetch, base::FEATURE_ENABLED_BY_DEFAULT);
#endif  // BUILDFLAG(IS_ANDROID)

#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
BASE_FEATURE(kOnConnectNative, base::FEATURE_DISABLED_BY_DEFAULT);
#endif

#if BUILDFLAG(IS_ANDROID)
// Enables or disables the OOM intervention.
BASE_FEATURE(kOomIntervention, base::FEATURE_ENABLED_BY_DEFAULT);
#endif

#if BUILDFLAG(IS_WIN)
// Changes behavior of App Launch Prefetch to ignore chrome browser launches
// after acquiry of the singleton.
BASE_FEATURE(kOverridePrefetchOnSingleton, base::FEATURE_DISABLED_BY_DEFAULT);
#endif

// Allows Chrome to do preconnect when prerender fails.
BASE_FEATURE(kPrerenderFallbackToPreconnect, base::FEATURE_DISABLED_BY_DEFAULT);

#if BUILDFLAG(IS_CHROMEOS)
// If enabled, use managed per-printer print job options set via
// DevicePrinters/PrinterBulkConfiguration policy in print preview.
BASE_FEATURE(kUseManagedPrintJobOptionsInPrintPreview,
             base::FEATURE_ENABLED_BY_DEFAULT);
#endif

BASE_FEATURE(kUserValueDefaultBrowserStrings,
             base::FEATURE_DISABLED_BY_DEFAULT);

// Shows a confirmation dialog when updates to a PWAs icon has been detected.
BASE_FEATURE(kPwaUpdateDialogForIcon, base::FEATURE_DISABLED_BY_DEFAULT);

// Enables using quiet prompts for notification permission requests.
BASE_FEATURE(kQuietNotificationPrompts, base::FEATURE_ENABLED_BY_DEFAULT);

// Enables recording additional web app related debugging data to be displayed
// in: chrome://web-app-internals
BASE_FEATURE(kRecordWebAppDebugInfo, base::FEATURE_DISABLED_BY_DEFAULT);

// Enables notification permission revocation for abusive origins.
BASE_FEATURE(kAbusiveNotificationPermissionRevocation,
             "AbusiveOriginNotificationPermissionRevocation",
             base::FEATURE_ENABLED_BY_DEFAULT);

#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
BASE_FEATURE(kSafetyHubExtensionsUwSTrigger, base::FEATURE_ENABLED_BY_DEFAULT);
// Enables extensions that do not display proper privacy practices in the
// Safety Hub Extension Reivew Panel.
BASE_FEATURE(kSafetyHubExtensionsNoPrivacyPracticesTrigger,
             base::FEATURE_ENABLED_BY_DEFAULT);
// Enables offstore extensions to be shown in the Safety Hub Extension
// review panel.
BASE_FEATURE(kSafetyHubExtensionsOffStoreTrigger,
             base::FEATURE_ENABLED_BY_DEFAULT);
#endif

BASE_FEATURE(kSafetyHubThreeDotDetails, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kSafetyHubDisruptiveNotificationRevocation,
             base::FEATURE_ENABLED_BY_DEFAULT);

constexpr base::FeatureParam<bool>
    kSafetyHubDisruptiveNotificationRevocationShadowRun{
        &kSafetyHubDisruptiveNotificationRevocation,
        /*name=*/"shadow_run", /*default_value=*/false};

#if BUILDFLAG(IS_ANDROID)
constexpr base::FeatureParam<int>
    kSafetyHubDisruptiveNotificationRevocationExperimentVersion{
        &kSafetyHubDisruptiveNotificationRevocation,
        /*name=*/"experiment_version", /*default_value=*/1};

constexpr base::FeatureParam<int>
    kSafetyHubDisruptiveNotificationRevocationMinNotificationCount{
        &kSafetyHubDisruptiveNotificationRevocation,
        /*name=*/"min_notification_count", /*default_value=*/4};

constexpr base::FeatureParam<base::TimeDelta>
    kSafetyHubDisruptiveNotificationRevocationWaitingTimeAsProposed{
        &kSafetyHubDisruptiveNotificationRevocation,
        /*name=*/"waiting_time_as_proposed", /*default_value=*/base::Days(4)};

constexpr base::FeatureParam<int>
    kSafetyHubDisruptiveNotificationRevocationNotificationTimeoutSeconds{
        &kSafetyHubDisruptiveNotificationRevocation,
        /*name=*/"notification_timeout_seconds",
        /*default_value=*/7 * 24 * 3600};
#else
constexpr base::FeatureParam<int>
    kSafetyHubDisruptiveNotificationRevocationExperimentVersion{
        &kSafetyHubDisruptiveNotificationRevocation,
        /*name=*/"experiment_version", /*default_value=*/2};

constexpr base::FeatureParam<int>
    kSafetyHubDisruptiveNotificationRevocationMinNotificationCount{
        &kSafetyHubDisruptiveNotificationRevocation,
        /*name=*/"min_notification_count", /*default_value=*/6};

constexpr base::FeatureParam<base::TimeDelta>
    kSafetyHubDisruptiveNotificationRevocationWaitingTimeAsProposed{
        &kSafetyHubDisruptiveNotificationRevocation,
        /*name=*/"waiting_time_as_proposed", /*default_value=*/base::Days(14)};
#endif

constexpr base::FeatureParam<double>
    kSafetyHubDisruptiveNotificationRevocationMaxEngagementScore{
        &kSafetyHubDisruptiveNotificationRevocation,
        /*name=*/"max_engagement_score", /*default_value=*/0.0};

constexpr base::FeatureParam<int>
    kSafetyHubDisruptiveNotificationRevocationMinFalsePositiveCooldown{
        &kSafetyHubDisruptiveNotificationRevocation,
        /*name=*/"min_false_positive_cooldown", /*default_value=*/0};

constexpr base::FeatureParam<int>
    kSafetyHubDisruptiveNotificationRevocationMaxFalsePositivePeriod{
        &kSafetyHubDisruptiveNotificationRevocation,
        /*name=*/"max_false_positive_period", /*default_value=*/14};

// TODO(crbug.com/406472515): Site engagement score increase on navigation
// happens at the same time as us detecting the navigation. If the score delta
// is 0, the initial navigation won't trigger marking the site as false
// positive.
constexpr base::FeatureParam<double>
    kSafetyHubDisruptiveNotificationRevocationMinSiteEngagementScoreDelta{
        &kSafetyHubDisruptiveNotificationRevocation,
        /*name=*/"min_engagement_score_delta", /*default_value=*/3.0};

constexpr base::FeatureParam<int>
    kSafetyHubDisruptiveNotificationRevocationUserRegrantWaitingPeriod{
        &kSafetyHubDisruptiveNotificationRevocation,
        /*name=*/"user_regrant_waiting_period", /*default_value=*/7};

constexpr base::FeatureParam<int>
    kSafetyHubDisruptiveNotificationRevocationWaitingForMetricsDays{
        &kSafetyHubDisruptiveNotificationRevocation,
        /*name=*/"waiting_for_metrics_days", /*default_value=*/1};

#if BUILDFLAG(IS_ANDROID)
// Enables Weak and Reused passwords in Safety Hub.
BASE_FEATURE(kSafetyHubWeakAndReusedPasswords,
             base::FEATURE_DISABLED_BY_DEFAULT);

// Enables the local passwords module in Safety Hub.
BASE_FEATURE(kSafetyHubLocalPasswordsModule, base::FEATURE_DISABLED_BY_DEFAULT);

// Enables the unified passwords module in Safety Hub.
BASE_FEATURE(kSafetyHubUnifiedPasswordsModule,
             base::FEATURE_DISABLED_BY_DEFAULT);
#endif  // BUILDFLAG(IS_ANDROID)

#if !BUILDFLAG(IS_ANDROID)
// Enables or disables the Trust Safety Sentiment Survey for Safety Hub.
BASE_FEATURE(kSafetyHubTrustSafetySentimentSurvey,
             "TrustSafetySentimentSurveyForSafetyHub",
             base::FEATURE_DISABLED_BY_DEFAULT);
#endif  // !BUILDFLAG(IS_ANDROID)

// SCT auditing hashdance allows Chrome clients who are not opted-in to Enhanced
// Safe Browsing Reporting to perform a k-anonymous query to see if Google knows
// about an SCT seen in the wild. If it hasn't been seen, then it is considered
// a security incident and uploaded to Google.
BASE_FEATURE(kSCTAuditingHashdance, base::FEATURE_ENABLED_BY_DEFAULT);

// An estimated high bound for the time it takes Google to ingest updates to an
// SCT log. Chrome will wait for at least this time plus the Log's Maximum Merge
// Delay after an SCT's timestamp before performing a hashdance lookup query.
const base::FeatureParam<base::TimeDelta> kSCTLogExpectedIngestionDelay{
    &kSCTAuditingHashdance,
    "sct_log_expected_ingestion_delay",
    base::Hours(1),
};

// A random delay will be added to the expected log ingestion delay between zero
// and this maximum. This prevents a burst of queries once a new SCT is issued.
const base::FeatureParam<base::TimeDelta> kSCTLogMaxIngestionRandomDelay{
    &kSCTAuditingHashdance,
    "sct_log_max_ingestion_random_delay",
    base::Hours(1),
};

// When enabled, an extension service worker's render process is given
// foreground priority while the worker is STARTING. Extension service workers
// are often started headlessly (e.g. to register webRequest listeners) with no
// controllee or other foreground signal, so their process would otherwise be
// left at background priority (which maps to EcoQoS on Windows). Under heavy
// system load that lets the worker starve, miss the start timeout, get torn
// down, and retry indefinitely (crbug.com/484218883). The boost is dropped once
// the worker reaches RUNNING or stops.
BASE_FEATURE(kServiceWorkerForegroundOnExtensionStartup,
             base::FEATURE_ENABLED_BY_DEFAULT);

// When enabled, a performance manager voter keeps the renderer process of an
// extension service worker at foreground priority for as long as the worker
// lives, but only when the extension holds the `webRequestBlocking` permission.
// Those workers synchronously gate navigations and network requests, so letting
// their process drop to background priority (EcoQoS on Windows) stalls the
// browsing session (crbug.com/484218883). This is the narrowly scoped
// counterpart to performance_manager::features::kExtensionServiceWorkerVoter,
// which boosts every extension service worker and regressed performance metrics
// (crbug.com/493556675).
BASE_FEATURE(kExtensionServiceWorkerPriorityVoter,
             base::FEATURE_ENABLED_BY_DEFAULT);

// Alternative to switches::kSitePerProcess, for turning on full site isolation.
// Launch bug: https://crbug.com/810843.  This is a //chrome-layer feature to
// avoid turning on site-per-process by default for *all* //content embedders
// (e.g. this approach lets ChromeCast avoid site-per-process mode).
//
// TODO(alexmos): Move this and the other site isolation features below to
// browser_features, as they are only used on the browser side.
BASE_FEATURE(kSitePerProcess,
#if BUILDFLAG(IS_ANDROID)
             base::FEATURE_DISABLED_BY_DEFAULT
#else
             base::FEATURE_ENABLED_BY_DEFAULT
#endif
);

// The default behavior to opt devtools users out of
// kProcessPerSiteUpToMainFrameThreshold.
BASE_FEATURE(kProcessPerSiteSkipDevtoolsUsers,
             base::FEATURE_DISABLED_BY_DEFAULT);

// The default behavior to opt enterprise users out of
// kProcessPerSiteUpToMainFrameThreshold.
BASE_FEATURE(kProcessPerSiteSkipEnterpriseUsers,
             base::FEATURE_ENABLED_BY_DEFAULT);

// Restricts "ProcessPerSiteUpToMainFrameThreshold" to the default search
// engine. Has no effect if "ProcessPerSiteUpToMainFrameThreshold" is disabled.
// Note: The "ProcessPerSiteUpToMainFrameThreshold" feature is defined in
// //content.

BASE_FEATURE(kProcessPerSiteForDSE,
#if BUILDFLAG(IS_ANDROID)
             base::FEATURE_DISABLED_BY_DEFAULT
#else
             base::FEATURE_ENABLED_BY_DEFAULT
#endif
);

#if BUILDFLAG(IS_CHROMEOS)
// Enables Camera Cloud Storage for saving photos and videos on Google Drive
// or OneDrive, controlled by CameraSaveLocation policy.
BASE_FEATURE(kCameraCloudStorage, base::FEATURE_ENABLED_BY_DEFAULT);

// Enables the SkyVault (cloud-first) changes, some of which are also controlled
// by policies: removing local storage, saving downloads and screen captures to
// the cloud, and related UX changes, primarily in the Files App.
BASE_FEATURE(kSkyVault, base::FEATURE_ENABLED_BY_DEFAULT);

#endif  // BUILDFLAG(IS_CHROMEOS)

// Disable downloads of unsafe file types over insecure transports if initiated
// from a secure page. As of M89, mixed downloads are blocked on all platforms.
BASE_FEATURE(kTreatUnsafeDownloadsAsActive, base::FEATURE_ENABLED_BY_DEFAULT);

// TrustSafetySentimentSurvey
#if !BUILDFLAG(IS_ANDROID)
// Enables surveying of users of Trust & Safety features with HaTS.
BASE_FEATURE(kTrustSafetySentimentSurvey, base::FEATURE_DISABLED_BY_DEFAULT);
// The minimum and maximum time after a user has interacted with a Trust and
// Safety they are eligible to be surveyed.
const base::FeatureParam<base::TimeDelta>
    kTrustSafetySentimentSurveyMinTimeToPrompt{
        &kTrustSafetySentimentSurvey, "min-time-to-prompt", base::Minutes(2)};
const base::FeatureParam<base::TimeDelta>
    kTrustSafetySentimentSurveyMaxTimeToPrompt{
        &kTrustSafetySentimentSurvey, "max-time-to-prompt", base::Minutes(60)};
// The maximum and minimum range for the random number of NTPs that the user
// must at least visit after interacting with a Trust and Safety feature to be
// eligible for a survey.
const base::FeatureParam<int> kTrustSafetySentimentSurveyNtpVisitsMinRange{
    &kTrustSafetySentimentSurvey, "ntp-visits-min-range", 2};
const base::FeatureParam<int> kTrustSafetySentimentSurveyNtpVisitsMaxRange{
    &kTrustSafetySentimentSurvey, "ntp-visits-max-range", 4};
// The feature area probabilities for each feature area considered as part of
// the Trust & Safety sentiment survey.
const base::FeatureParam<double>
    kTrustSafetySentimentSurveyPrivacySettingsProbability{
        &kTrustSafetySentimentSurvey, "privacy-settings-probability", 0.6};
const base::FeatureParam<double>
    kTrustSafetySentimentSurveyTrustedSurfaceProbability{
        &kTrustSafetySentimentSurvey, "trusted-surface-probability", 0.4};
const base::FeatureParam<double>
    kTrustSafetySentimentSurveyTransactionsProbability{
        &kTrustSafetySentimentSurvey, "transactions-probability", 0.05};
// The HaTS trigger IDs, which determine which survey is delivered from the HaTS
// backend.
const base::FeatureParam<std::string>
    kTrustSafetySentimentSurveyPrivacySettingsTriggerId{
        &kTrustSafetySentimentSurvey, "privacy-settings-trigger-id", ""};
const base::FeatureParam<std::string>
    kTrustSafetySentimentSurveyTrustedSurfaceTriggerId{
        &kTrustSafetySentimentSurvey, "trusted-surface-trigger-id", ""};
const base::FeatureParam<std::string>
    kTrustSafetySentimentSurveyTransactionsTriggerId{
        &kTrustSafetySentimentSurvey, "transactions-trigger-id", ""};
// The time the user must remain on settings after interacting with a privacy
// setting to be considered.
const base::FeatureParam<base::TimeDelta>
    kTrustSafetySentimentSurveyPrivacySettingsTime{&kTrustSafetySentimentSurvey,
                                                   "privacy-settings-time",
                                                   base::Seconds(20)};
// The time the user must have the Trusted Surface bubble open to be considered.
// Alternatively the user can interact with the bubble, in which case this time
// is irrelevant.
const base::FeatureParam<base::TimeDelta>
    kTrustSafetySentimentSurveyTrustedSurfaceTime{
        &kTrustSafetySentimentSurvey, "trusted-surface-time", base::Seconds(5)};
// The time the user must remain on settings after visiting the password
// manager page.
const base::FeatureParam<base::TimeDelta>
    kTrustSafetySentimentSurveyTransactionsPasswordManagerTime{
        &kTrustSafetySentimentSurvey, "transactions-password-manager-time",
        base::Seconds(20)};

#endif

// TrustSafetySentimentSurveyV2
#if !BUILDFLAG(IS_ANDROID)
// Enables the second version of the sentiment survey for users of Trust &
// Safety features, using HaTS.
BASE_FEATURE(kTrustSafetySentimentSurveyV2, base::FEATURE_ENABLED_BY_DEFAULT);
// The minimum and maximum time after a user has interacted with a Trust and
// Safety feature that they are eligible to be surveyed.
const base::FeatureParam<base::TimeDelta>
    kTrustSafetySentimentSurveyV2MinTimeToPrompt{
        &kTrustSafetySentimentSurveyV2, "min-time-to-prompt", base::Minutes(2)};
const base::FeatureParam<base::TimeDelta>
    kTrustSafetySentimentSurveyV2MaxTimeToPrompt{&kTrustSafetySentimentSurveyV2,
                                                 "max-time-to-prompt",
                                                 base::Minutes(60)};
// The maximum and minimum range for the random number of NTPs that the user
// must at least visit after interacting with a Trust and Safety feature to be
// eligible for a survey.
const base::FeatureParam<int> kTrustSafetySentimentSurveyV2NtpVisitsMinRange{
    &kTrustSafetySentimentSurveyV2, "ntp-visits-min-range", 2};
const base::FeatureParam<int> kTrustSafetySentimentSurveyV2NtpVisitsMaxRange{
    &kTrustSafetySentimentSurveyV2, "ntp-visits-max-range", 4};
// The minimum time that has to pass in the current session before a user can be
// eligible to be considered for the baseline control group.
const base::FeatureParam<base::TimeDelta>
    kTrustSafetySentimentSurveyV2MinSessionTime{
        &kTrustSafetySentimentSurveyV2, "min-session-time", base::Seconds(30)};
// The feature area probabilities for each feature area considered as part of
// the Trust & Safety sentiment survey.
// TODO(crbug.com/40245476): Calculate initial probabilities and remove 0.0
const base::FeatureParam<double>
    kTrustSafetySentimentSurveyV2BrowsingDataProbability{
        &kTrustSafetySentimentSurveyV2, "browsing-data-probability", 0.006};
const base::FeatureParam<double>
    kTrustSafetySentimentSurveyV2ControlGroupProbability{
        &kTrustSafetySentimentSurveyV2, "control-group-probability", 0.000025};
const base::FeatureParam<double>
    kTrustSafetySentimentSurveyV2DownloadWarningUIProbability{
        &kTrustSafetySentimentSurveyV2, "download-warning-ui-probability",
        0.05213384};
const base::FeatureParam<double>
    kTrustSafetySentimentSurveyV2PasswordCheckProbability{
        &kTrustSafetySentimentSurveyV2, "password-check-probability", 0.195};
const base::FeatureParam<double>
    kTrustSafetySentimentSurveyV2PasswordProtectionUIProbability{
        &kTrustSafetySentimentSurveyV2, "password-protection-ui-probability",
        0.5};
const base::FeatureParam<double>
    kTrustSafetySentimentSurveyV2SafetyCheckProbability{
        &kTrustSafetySentimentSurveyV2, "safety-check-probability", 0.12121};
const base::FeatureParam<double>
    kTrustSafetySentimentSurveyV2SafetyHubNotificationProbability{
        &kTrustSafetySentimentSurveyV2, "safety-hub-notification-probability",
        0.0};
const base::FeatureParam<double>
    kTrustSafetySentimentSurveyV2SafetyHubInteractionProbability{
        &kTrustSafetySentimentSurveyV2, "safety-hub-interaction-probability",
        0.0};
const base::FeatureParam<double>
    kTrustSafetySentimentSurveyV2TrustedSurfaceProbability{
        &kTrustSafetySentimentSurveyV2, "trusted-surface-probability",
        0.012685};
const base::FeatureParam<double>
    kTrustSafetySentimentSurveyV2PrivacyGuideProbability{
        &kTrustSafetySentimentSurveyV2, "privacy-guide-probability", 0.5};
const base::FeatureParam<double>
    kTrustSafetySentimentSurveyV2SafeBrowsingInterstitialProbability{
        &kTrustSafetySentimentSurveyV2,
        "safe-browsing-interstitial-probability", 0.18932671};
// The HaTS trigger IDs, which determine which survey is delivered from the HaTS
// backend.
const base::FeatureParam<std::string>
    kTrustSafetySentimentSurveyV2BrowsingDataTriggerId{
        &kTrustSafetySentimentSurveyV2, "browsing-data-trigger-id",
        "1iSgej9Tq0ugnJ3q1cK0QwXZ12oo"};
const base::FeatureParam<std::string>
    kTrustSafetySentimentSurveyV2ControlGroupTriggerId{
        &kTrustSafetySentimentSurveyV2, "control-group-trigger-id",
        "CXMbsBddw0ugnJ3q1cK0QJM1Hu8m"};
const base::FeatureParam<std::string>
    kTrustSafetySentimentSurveyV2DownloadWarningUITriggerId{
        &kTrustSafetySentimentSurveyV2, "download-warning-ui-trigger-id",
        "7SS4sg4oR0ugnJ3q1cK0TNvCvd8U"};
const base::FeatureParam<std::string>
    kTrustSafetySentimentSurveyV2PasswordCheckTriggerId{
        &kTrustSafetySentimentSurveyV2, "password-check-trigger-id",
        "Xd54YDVNJ0ugnJ3q1cK0UYBRruNH"};
const base::FeatureParam<std::string>
    kTrustSafetySentimentSurveyV2PasswordProtectionUITriggerId{
        &kTrustSafetySentimentSurveyV2, "password-protection-ui-trigger-id",
        "bQBRghu5w0ugnJ3q1cK0RrqdqVRP"};
const base::FeatureParam<std::string>
    kTrustSafetySentimentSurveyV2SafetyCheckTriggerId{
        &kTrustSafetySentimentSurveyV2, "safety-check-trigger-id",
        "YSDfPVMnX0ugnJ3q1cK0RxEhwkay"};
const base::FeatureParam<std::string>
    kTrustSafetySentimentSurveyV2SafetyHubInteractionTriggerId{
        &kTrustSafetySentimentSurveyV2, "safety-hub-interaction-trigger-id",
        ""};
const base::FeatureParam<std::string>
    kTrustSafetySentimentSurveyV2SafetyHubNotificationTriggerId{
        &kTrustSafetySentimentSurveyV2, "safety-hub-notification-trigger-id",
        ""};
const base::FeatureParam<std::string>
    kTrustSafetySentimentSurveyV2TrustedSurfaceTriggerId{
        &kTrustSafetySentimentSurveyV2, "trusted-surface-trigger-id",
        "CMniDmzgE0ugnJ3q1cK0U6PaEn1f"};
const base::FeatureParam<std::string>
    kTrustSafetySentimentSurveyV2PrivacyGuideTriggerId{
        &kTrustSafetySentimentSurveyV2, "privacy-guide-trigger-id",
        "tqR1rjeDu0ugnJ3q1cK0P9yJEq7Z"};
const base::FeatureParam<std::string>
    kTrustSafetySentimentSurveyV2SafeBrowsingInterstitialTriggerId{
        &kTrustSafetySentimentSurveyV2, "safe-browsing-interstitial-trigger-id",
        "Z9pSWP53n0ugnJ3q1cK0Y6YkGRpU"};
// The time the user must have the Trusted Surface bubble open to be considered.
// Alternatively the user can interact with the bubble, in which case this time
// is irrelevant.
const base::FeatureParam<base::TimeDelta>
    kTrustSafetySentimentSurveyV2TrustedSurfaceTime{
        &kTrustSafetySentimentSurveyV2, "trusted-surface-time",
        base::Seconds(5)};
#endif

#if !BUILDFLAG(IS_ANDROID)
BASE_FEATURE(kWebAppPeriodicPreinstallUpdate, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kWebAppMigratePreinstalledChat, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kWebAppInstallDialog, base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kWebAppInstallDialogWinPin, base::FEATURE_DISABLED_BY_DEFAULT);

// When this feature is enabled, the web app sync code will process the
// `migrated_from_manifest_id` field in its sync data to possibly treat new
// applications that come in via sync as being the result of a migration.
// Unless `blink::features::kWebAppMigrationApi` is enabled on some other
// synced profile, no such data should exist in sync.
BASE_FEATURE(kWebAppHandleAppMigrationViaSync,
             base::FEATURE_ENABLED_BY_DEFAULT);
#endif  // !BUILDFLAG(IS_ANDROID)

BASE_FEATURE(kWebAppUpgradeToDatabaseVersion6,
             base::FEATURE_ENABLED_BY_DEFAULT);

#if !BUILDFLAG(IS_ANDROID)
BASE_FEATURE(kWebium, base::FEATURE_DISABLED_BY_DEFAULT);
// When enable, the reload button will be replaced with the a WebView, and
// chrome://webui-toolbar.top-chrome will be loaded as the content.
// crbug.com/444358999
BASE_FEATURE(kWebUIReloadButton, base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kWebUIToolbarProcessOverheadExperiment,
             base::FEATURE_DISABLED_BY_DEFAULT);
// Switches location bar over to a WebUI implementation.
// See crbug.com/470042732
BASE_FEATURE(kWebUILocationBar, base::FEATURE_DISABLED_BY_DEFAULT);

// When this is enabled, all the checks for enabled individual WebUI toolbar
// controls in chrome/browser/ui/ui_features.h will return true.
BASE_FEATURE(kWebUIToolbar, base::FEATURE_DISABLED_BY_DEFAULT);

// Controls whether the WebUI toolbar WebContents opts out of frame eviction.
BASE_FEATURE(kWebUIToolbarFrameEvictionOptOut,
             base::FEATURE_DISABLED_BY_DEFAULT);

// The following feature params control the crash recovery behavior of the Web
// UI reload button. If the renderer crashes, we will try to recover it by
// reloading the contents until the number of crashes reaches
// `kWebUIReloadButtonMaxCrashRecoveryTimes`. If the maximum number of crash
// counts is reached, no recovery will be attempted until
// `WebUIReloadButtonCrashRecoverRetryInterval` later. The counter will reset if
// there is no crash within `WebUIReloadButtonCrashRecoverResetInterval`.
// Here is an example with the default settings.
// - 00:00 renderer crashes
// - 00:00 recovery is triggered
// - 00:05 renderer crashes
// - 00:05 recovery is triggered
// - 00:16 renderer crashes
// - 00:16 recovery is triggered, as it has been >= 10s and the counter is reset
// - 00:17 renderer crashes
// - 00:17 recovery is triggered
// - 00:18 renderer crashes
// - 01:18 recovery is triggered, it's not immediate because the it exceeds the
//         max recovery times, but it will retry after 1 minute
const base::FeatureParam<int> kWebUIReloadButtonMaxCrashRecoveryTimes{
    &kWebUIReloadButton, "WebUIReloadButtonMaxCrashRecoveryTimes", 3};
const base::FeatureParam<base::TimeDelta>
    kWebUIReloadButtonCrashRecoverResetInterval{
        &kWebUIReloadButton, "WebUIReloadButtonCrashRecoverResetInterval",
        base::Seconds(10)};
const base::FeatureParam<base::TimeDelta>
    kWebUIReloadButtonCrashRecoverRetryInterval{
        &kWebUIReloadButton, "WebUIReloadButtonCrashRecoverRetryInterval",
        base::Minutes(1)};

// When enabled, initial WebUI renderers that become unresponsive will be
// restarted without showing the hung renderer dialog.
// `WebUIReloadButtonRestartUnresponsiveRenderersTimeout` controls the timeout
// for unresponsive renderers.
// See crbug.com/475397687.
const base::FeatureParam<bool> kWebUIReloadButtonRestartUnresponsive{
    &kWebUIReloadButton, "WebUIReloadButtonRestartUnresponsive", false};
const base::FeatureParam<base::TimeDelta>
    kWebUIReloadButtonRestartUnresponsiveRenderersTimeout{
        &kWebUIReloadButton,
        "WebUIReloadButtonRestartUnresponsiveRenderersTimeout",
        base::Seconds(15)};

// When this is enabled, the `BrowserView` will not show until the reload button
// has finished loading.
const base::FeatureParam<bool> kWebUIReloadButtonDeferBrowserViewShow{
    &kWebUIReloadButton, "WebUIReloadButtonDeferBrowserViewShow", false};
// When this is enabled, the WebUI toolbar will be pre-warmed during browser
// initialization.
const base::FeatureParam<bool> kWebUIReloadButtonPrewarmWebUI{
    &kWebUIReloadButton, "WebUIReloadButtonPrewarmWebUI", false};
// When this is enabled, the pre-warmed WebUI will also navigate immediately. It
// only takes effect when `WebUIReloadButtonPrewarmWebUI` is enabled.
const base::FeatureParam<bool> kWebUIReloadButtonPrewarmWebUIPreNavigate{
    &kWebUIReloadButton, "WebUIReloadButtonPrewarmWebUIPreNavigate", false};
// When this is enabled, the WebUI toolbar will be pre-warmed at profile ready
// time instead of browser initialization time. It only takes effect when
// `WebUIReloadButtonPrewarmWebUI` is enabled.
const base::FeatureParam<bool> kWebUIReloadButtonProfilePrewarming{
    &kWebUIReloadButton, "WebUIReloadButtonProfilePrewarming", false};
// When this is enabled, the reload button will be marked as visible until its
// first non-empty paint.
const base::FeatureParam<bool> kWebUIReloadButtonKeepVisibleUntilPaint{
    &kWebUIReloadButton, "WebUIReloadButtonKeepVisibleUntilPaint", false};
// When enabled, bypasses creating URL loader throttles for WebUI resources
// during startup.
const base::FeatureParam<bool> kWebUIReloadButtonBypassLoaderThrottles{
    &kWebUIReloadButton, "WebUIReloadButtonBypassLoaderThrottles", false};
// When enabled, the split tabs button will be replaced with WebUI loaded from
// chrome://webui-toolbar.top-chrome.
// crbug.com/470039098
BASE_FEATURE(kWebUISplitTabsButton, base::FEATURE_DISABLED_BY_DEFAULT);
// When enabled, the home button will be replaced with WebUI loaded from
// chrome://webui-toolbar.top-chrome.
// crbug.com/470039765
BASE_FEATURE(kWebUIHomeButton, base::FEATURE_DISABLED_BY_DEFAULT);

// When enabled, the battery saver button will be replaced with WebUI loaded
// from chrome://webui-toolbar.top-chrome. crbug.com/503821930
BASE_FEATURE(kWebUIBatterySaverButton, base::FEATURE_DISABLED_BY_DEFAULT);

// When enabled, the performance intervention button will be replaced with WebUI
// loaded from chrome://webui-toolbar.top-chrome. crbug.com/503822129
BASE_FEATURE(kWebUIPerformanceInterventionButton,
             base::FEATURE_DISABLED_BY_DEFAULT);

// When enabled, the app menu button will be replaced with WebUI loaded from
// chrome://webui-toolbar.top-chrome.
BASE_FEATURE(kWebUIAppMenuButton, base::FEATURE_DISABLED_BY_DEFAULT);

// When enabled, the back/forward buttons will be replaced with WebUI loaded
// from chrome://webui-toolbar.top-chrome.
// crbug.com/470038385
BASE_FEATURE(kWebUIBackForwardButton, base::FEATURE_DISABLED_BY_DEFAULT);

// When enabled, the pinned toolbar actions will be replaced with WebUI loaded
// from chrome://webui-toolbar.top-chrome.
// crbug.com/474061420
BASE_FEATURE(kWebUIPinnedToolbarActions, base::FEATURE_DISABLED_BY_DEFAULT);

// When enabled, the extensions container will be replaced with WebUI loaded
// from chrome://webui-toolbar.top-chrome.
BASE_FEATURE(kWebUIExtensionsContainer, base::FEATURE_DISABLED_BY_DEFAULT);

#endif  // !BUILDFLAG(IS_ANDROID)

// Enables the User-Agent override fix for SearchPrefetch. This will work only
// if enabled together with `kPreloadingRespectUserAgentOverride`.
BASE_FEATURE(kRespectUserAgentOverrideInSearchPrefetch,
             base::FEATURE_DISABLED_BY_DEFAULT);

// Restricts the WebUI scripts able to use the generated code cache according to
// embedder-specified heuristics.
BASE_FEATURE(kRestrictedWebUICodeCache, base::FEATURE_DISABLED_BY_DEFAULT);

// Defines a comma-separated list of resource names able to use the generated
// code cache when RestrictedWebUICodeCache is enabled.
const base::FeatureParam<std::string> kRestrictedWebUICodeCacheResources{
    &kRestrictedWebUICodeCache, "RestrictedWebUICodeCacheResources", ""};

#if BUILDFLAG(IS_CHROMEOS)
// Populates storage dimensions in UMA log if enabled. Requires diagnostics
// package in the image.
BASE_FEATURE(kUmaStorageDimensions, base::FEATURE_DISABLED_BY_DEFAULT);
#endif

#if BUILDFLAG(IS_WIN)
// Kill switch for pinning PWA Shortcut to the Windows taskbar with the Taskbar
// pinning Limited Access Feature.
BASE_FEATURE(kWinPinPWAShortcutWithLAF, base::FEATURE_ENABLED_BY_DEFAULT);
#endif  // BUILDFLAG(IS_WIN)

#if BUILDFLAG(IS_CHROMEOS)

// A feature to enable periodic log class management enabled policy.
BASE_FEATURE(kClassManagementEnabledMetricsProvider,
             base::FEATURE_ENABLED_BY_DEFAULT);

#endif  // BUILDFLAG(IS_CHROMEOS)

#if !BUILDFLAG(IS_ANDROID)
// A feature to enable smart restart metrics collection. The collected metrics
// will be used to make informed decisions about the future of the smart restart
// feature.
BASE_FEATURE(kSmartRestartMetrics, base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kSmartRestart, base::FEATURE_ENABLED_BY_DEFAULT);

const base::FeatureParam<base::TimeDelta> kSmartRestartDelay{
    &kSmartRestart, "restart_delay", base::Minutes(1)};

BASE_FEATURE(kSmartRestartLockScreen, base::FEATURE_DISABLED_BY_DEFAULT);

const base::FeatureParam<int> kSmartRestartLockScreenTabThreshold{
    &kSmartRestartLockScreen, "lock_tab_threshold", -1};

const base::FeatureParam<int> kSmartRestartLockScreenDisruptionThreshold{
    &kSmartRestartLockScreen, "lock_disruption_threshold", 2};

const base::FeatureParam<base::TimeDelta> kSmartRestartLockScreenDelay{
    &kSmartRestartLockScreen, "lock_restart_delay", base::Minutes(5)};

const base::FeatureParam<double> kSmartRestartLockBypassBeforeUnloadThreshold{
    &kSmartRestartLockScreen, "lock_bypass_beforeunload_threshold", -1.0};

#if BUILDFLAG(IS_WIN)
// When enabled, the browser process will pass its own process handle to the
// relaunched child process, and the child will block early startup until
// the parent exits to prevent profile lock contention.
BASE_FEATURE(kRelaunchWaitForParentProcess, base::FEATURE_DISABLED_BY_DEFAULT);
#endif

// A feature to record the difference in the number of tabs and windows between
// the last session and the current session on restart.
BASE_FEATURE(kRecordTabWindowDiffOnRestart, base::FEATURE_ENABLED_BY_DEFAULT);
#endif  // BUILDFLAG(IS_ANDROID)

}  // namespace features
