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

#ifndef COMPONENTS_OPTIMIZATION_GUIDE_CORE_OPTIMIZATION_GUIDE_FEATURES_H_
#define COMPONENTS_OPTIMIZATION_GUIDE_CORE_OPTIMIZATION_GUIDE_FEATURES_H_

// Guidelines for adding new features:
// 1. Don't add new features in this file. Put them somewhere near the thing
//    they control or the interface they affect the behavior of.
// 2. Features should be declared with a comment indicating what they are for
//    and some reference that can be used to decide when they are no longer
//    needed.
//     a. Rollout gates should link a tracker bug for the rollout.
//     b. Killswitches should link a playbook describing their usage scenarios.
//     c. Speculative parameters and debugging flags should indicate that
//        status, so they can be removed whenever they are inconvenient to keep.
// 3. Parameters should not be added to existing features. In general, it's
//    better to make an independent Feature for each parameter.
// 4. See //docs/flag_guarding_guidelines.md and //docs/configuration.md for
//    general best practices and advice for the Chromium repo.

// TODO: crbug.com/514743962 - All of these constants should be moved to more
// specific files and out of this file.  Do not add anything here.

#include <map>
#include <optional>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "base/byte_size.h"
#include "base/component_export.h"
#include "base/containers/enum_set.h"
#include "base/containers/flat_set.h"
#include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/optimization_guide/core/optimization_guide_enums.h"
#include "components/optimization_guide/proto/hints.pb.h"
#include "components/optimization_guide/proto/models.pb.h"
#include "components/optimization_guide/public/mojom/model_broker.mojom-shared.h"
#include "net/nqe/effective_connection_type.h"
#include "url/gurl.h"

namespace optimization_guide {

class MqlsFeatureMetadata;
namespace features {

COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kOptimizationHints);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kOptimizationGuideFetchingForSRP);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kOptimizationTargetPrediction);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kPageTextExtraction);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kPushNotifications);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kOptimizationGuideMetadataValidation);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kPreventLongRunningPredictionModels);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kOverrideNumThreadsForModelExecution);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kOptimizationGuidePersonalizedFetching);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kOptimizationGuidePredictionModelKillswitch);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kOptimizationGuideModelExecution);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kModelQualityLogging);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kLogOnDeviceMetricsOnStartup);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kTextSafetyScanLanguageDetection);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kOnDeviceModelFetchPerformanceClassEveryStartup);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kAiSettingsPageForceAvailable);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kAnnotatedPageContentWithActionableElements);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kAnnotatedPageContentWithMediaData);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kOptimizationGuideProactivePersonalizedHintsFetching);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kOptimizationGuideBypassFormsClassificationAuth);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kOptimizationGuideBypassPasswordChangeAuth);

// Allows setting feature params for model download configuration, such as
// minimum performance class for download.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kOnDeviceModelPerformanceParams);

// Comma-separated list of performance classes (e.g. "3,4,5") that should
// download the base model. Use "*" if there is no performance class
// requirement.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
extern const base::FeatureParam<std::string>
    kPerformanceClassListForOnDeviceModel;

// Comma-separated list of performance classes that should use a smaller model
// if available. This should be a subset of
// kPerformanceClassListForOnDeviceModel.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
extern const base::FeatureParam<std::string>
    kLowTierPerformanceClassListForOnDeviceModel;

// Comma-separated list of performance classes that have image input enabled.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
extern const base::FeatureParam<std::string> kPerformanceClassListForImageInput;

// Whether on device models are downloaded in background prior to feature usage.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kOnDeviceModelBackgroundDownload);

// Comma-separated list of features that are allowed to be downloaded in
// background.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
extern const base::FeatureParam<std::string>
    kOnDeviceModelBackgroundDownloadAllowedFeatures;

// Returns whether the feature is allowed to be downloaded in background.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
bool IsOnDeviceModelBackgroundDownloadEnabledForFeature(
    mojom::OnDeviceFeature feature);


// Whether model sessions may be brokered to untrusted processes.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kBrokerModelSessionsForUntrustedProcesses);

COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kGetAIPageContentSubframeTimeoutEnabled);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
extern const base::FeatureParam<base::TimeDelta>
    kGetAIPageContentSubframeTimeoutParam;

COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kGetAIPageContentMainFrameTimeoutEnabled);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
extern const base::FeatureParam<base::TimeDelta>
    kGetAIPageContentMainFrameTimeoutParam;

COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kGetAIPageContentGetImageBytesTimeoutEnabled);
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
extern const base::FeatureParam<base::TimeDelta>
    kGetAIPageContentGetImageBytesTimeoutParam;

typedef base::EnumSet<proto::RequestContext,
                      proto::RequestContext_MIN,
                      proto::RequestContext_MAX>
    RequestContextSet;

typedef base::EnumSet<proto::OptimizationType,
                      proto::OptimizationType_MIN,
                      proto::OptimizationType_MAX>
    OptimizationTypeSet;

// The grace period duration for how long to give outstanding page text dump
// requests to respond after DidFinishLoad.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
base::TimeDelta PageTextExtractionOutstandingRequestsGracePeriod();

// Whether hints for active tabs and top hosts should be batch updated.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
bool ShouldBatchUpdateHintsForActiveTabsAndTopHosts();

// Whether hints fetching for search results is enabled.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
bool IsSRPFetchingEnabled();
// The maximum number of search results allowed to be requested by the client to
// the remote Optimization Guide Service.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
size_t MaxResultsForSRPFetch();

// The API key for the One Platform Optimization Guide Service.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
std::string GetOptimizationGuideServiceAPIKey();

// The host for the One Platform Optimization Guide Service for Models and Host
// Model Features.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
GURL GetOptimizationGuideServiceGetModelsURL();

// Whether prediction of optimization targets is enabled.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
bool IsOptimizationTargetPredictionEnabled();

// Whether server optimization hints are enabled.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
bool IsOptimizationHintsEnabled();

// Returns true if the feature to use push notifications is enabled.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
bool IsPushNotificationsEnabled();

// Returns whether fetching hints for active tabs should happen on deferred
// startup. Otherwise active tabs hints will be fetched after a random interval
// between ActiveTabsHintsFetchRandomMinDelay() and
// ActiveTabsHintsFetchRandomMaxDelay().
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
bool ShouldDeferStartupActiveTabsHintsFetch();

// The maximum number of hints allowed to be maintained in a least-recently-used
// cache for hosts.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
size_t MaxHostKeyedHintCacheSize();

// Returns true if hints should be persisted to disk. If this is false, hints
// will just be stored in-memory and evicted if not recently used.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
bool ShouldPersistHintsToDisk();

// Returns requests contexts for which personalized metadata should be enabled.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
RequestContextSet GetAllowedContextsForPersonalizedMetadata();

// Returns optimization types for which proactive personalization should be
// enabled.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
OptimizationTypeSet GetAllowedOptimizationTypesForProactivePersonalization();

// Returns the minimum random delay before starting to fetch for prediction
// models and host model features.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
base::TimeDelta PredictionModelFetchRandomMinDelay();

// Returns the maximum random delay before starting to fetch for prediction
// models and host model features.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
base::TimeDelta PredictionModelFetchRandomMaxDelay();

// Returns the time to wait before retrying a failed fetch for prediction
// models.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
base::TimeDelta PredictionModelFetchRetryDelay();

// Returns the time to wait after browser start before fetching prediciton
// models.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
base::TimeDelta PredictionModelFetchStartupDelay();

// Returns the time to wait after a successful fetch of prediction models to
// refresh models.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
base::TimeDelta PredictionModelFetchInterval();

// Returns the random delay time to wait for starting a model fetch when a new
// optimization target observer registration happens, after the initial model
// fetch is completed.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
base::TimeDelta PredictionModelNewRegistrationFetchRandomDelay();

// Whether to use the model execution watchdog.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
bool IsModelExecutionWatchdogEnabled();

// The default timeout for the watchdog to use if none is given by the caller.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
base::TimeDelta ModelExecutionWatchdogDefaultTimeout();

// Returns whether the page entities model should be executed on page content
// for a user using |locale| as their browser language.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
bool ShouldExecutePageEntitiesModelOnPageContent(const std::string& locale);

// Returns whether the metadata validation fetch feature is host keyed.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
bool ShouldMetadataValidationFetchHostKeyed();

// Returns the number of threads to use for model inference on the given
// optimization target.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
std::optional<int> OverrideNumThreadsForOptTarget(
    proto::OptimizationTarget opt_target);

// Whether logging of model quality is enabled.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
bool IsModelQualityLoggingEnabled();

// Whether model quality logging is enabled for a feature.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
bool IsModelQualityLoggingEnabledForFeature(const MqlsFeatureMetadata*);

// Returns whether the `model_version` for `opt_target` is part of emergency
// killswitch, and this model should be stopped serving immediately.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
std::map<proto::OptimizationTarget, std::set<int64_t>>
GetPredictionModelVersionsInKillSwitch();

// Returns whether the on-device config should be loaded with higher priority.
// If true, all tasks for the on-device model execution config interpreter
// will be run with user visible priority.
inline constexpr bool
ShouldLoadOnDeviceModelExecutionConfigWithHigherPriority() {
  return true;
}

// Returns the idle timeout before the on device model service shuts down.
inline constexpr base::TimeDelta GetOnDeviceModelIdleTimeout() {
  return base::Minutes(1);
}

// Returns the delay before starting the on device model inference when
// running validation.
inline constexpr base::TimeDelta
GetOnDeviceModelExecutionValidationStartupDelay() {
  return base::Seconds(5);
}

// Returns the number of crashes without a successful response before the
// on-device model won't be used.
inline constexpr int GetOnDeviceModelCrashCountBeforeDisable() {
  return 3;
}

// Feature params for handling exponential backoff after crashes.
inline constexpr base::TimeDelta GetOnDeviceModelMaxCrashBackoffTime() {
  return base::Hours(1);
}
inline constexpr base::TimeDelta GetOnDeviceModelCrashBackoffBaseTime() {
  return base::Minutes(1);
}

COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
base::TimeDelta GetOnDeviceStartupMetricDelay();

// Whether on-device execution is enabled.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
bool IsOnDeviceExecutionEnabled();

// The amount of grace period to use from the last time the feature was used to
// consider it as recently used. Recent usage is one of the criteria for the
// base and adaptation on-device models to be downloaded.
inline constexpr base::TimeDelta
GetOnDeviceEligibleModelFeatureRecentUsePeriod() {
  return base::Days(30);
}

// The on-device model is fetched when the device is considered eligible for
// on-device execution. When the device stops being eligible, the model is
// retained for this amount of time. This protects the user from repeatedly
// downloading the model in the event eligibility fluctuates. for on-device
// evaluation
// See on_device_model_component.cc for how eligibility is computed.
inline constexpr base::TimeDelta GetOnDeviceModelRetentionTime() {
  return base::Days(30);
}

// Return the disk space required for on device model install.
inline constexpr base::ByteSize GetDiskSpaceRequiredForOnDeviceModelInstall() {
  return base::GiB(20);
}

// Return the disk space required to retain the on device model.
inline constexpr base::ByteSize GetDiskSpaceRequiredForOnDeviceModelRetain() {
  return base::GiB(5);
}

// Whether there is enough free disk space to allow on-device model
// installation.
inline constexpr bool IsFreeDiskSpaceSufficientForOnDeviceModelInstall(
    base::ByteSize free_disk_space_bytes) {
  return GetDiskSpaceRequiredForOnDeviceModelInstall() <= free_disk_space_bytes;
}

// Whether there is too little disk space to retain the on-device model
// installation.
inline constexpr bool IsFreeDiskSpaceTooLowForOnDeviceModelInstall(
    base::ByteSize free_disk_space_bytes) {
  return GetDiskSpaceRequiredForOnDeviceModelRetain() >= free_disk_space_bytes;
}

// Whether on-device model session creation is gated on sufficient disk space to
// build execution caches.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
BASE_DECLARE_FEATURE(kOnDeviceModelCachesDiskSpaceCheck);

// Whether there is too little disk space to build caches for the
// on-device model installed.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
bool IsFreeDiskSpaceTooLowForOnDeviceModelCachesBuild(
    base::ByteSize free_disk_space_bytes);

// Whether there is enough free disk space to allow on-device model
// installation proactively in background.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
bool IsFreeDiskSpaceSufficientForBackgroundOnDeviceModelInstall(
    base::ByteSize free_disk_space_bytes);

// These params configure the repetition checker. See HasRepeatingSuffix() in
// repetition_checker.h for explanation. A value of 2 for num repeats and 16 for
// min repeat chars would mean we will halt a response once it repeats at least
// 16 chars 2 times at the end of the response.
inline constexpr int GetOnDeviceModelNumRepeats() {
  return 2;
}
inline constexpr int GetOnDeviceModelMinRepeatChars() {
  return 16;
}

// Whether the response should be retracted if repeats are detected.
inline constexpr bool GetOnDeviceModelRetractRepeats() {
  return true;
}

// Settings to control output sampling.
inline constexpr int GetOnDeviceModelDefaultTopK() {
  return 64;
}
inline constexpr int GetOnDeviceModelMaxTopK() {
  return 128;
}
inline constexpr double GetOnDeviceModelDefaultTemperature() {
  return 1.0;
}

inline std::vector<uint32_t> GetOnDeviceModelAllowedAdaptationRanks() {
  return {32};
}

// Returns what the timeout for calls to GetAIPageContent should be for
// subframes. An empty return value indicates no timeout should be applied.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
std::optional<base::TimeDelta> GetSubframeGetAIPageContentTimeout();

// Returns what the timeout for calls to GetAIPageContent should be for
// the main frame. An empty return value indicates no timeout should be
// applied.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
std::optional<base::TimeDelta> GetMainFrameGetAIPageContentTimeout();

// Returns what the timeout for calls to GetImageBytes should be.
// An empty return value indicates no timeout should be applied.
COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
std::optional<base::TimeDelta> GetAIPageContentGetImageBytesTimeout();

// Overrides the Optimization Guide Service URL that the PredictionModelFetcher
// will request remote models and host features from.
inline constexpr char kOptimizationGuideServiceGetModelsURLSwitch[] =
    "optimization-guide-service-get-models-url";

}  // namespace features
}  // namespace optimization_guide

#endif  // COMPONENTS_OPTIMIZATION_GUIDE_CORE_OPTIMIZATION_GUIDE_FEATURES_H_
