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

#include "components/variations/service/variations_service.h"

#include <stddef.h>
#include <stdint.h>

#include <algorithm>
#include <optional>
#include <string_view>
#include <utility>
#include <vector>

#include "base/base64.h"
#include "base/command_line.h"
#include "base/debug/crash_logging.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/observer_list.h"
#include "base/strings/string_util.h"
#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "base/version.h"
#include "base/version_info/version_info.h"
#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "components/encrypted_messages/encrypted_message.pb.h"
#include "components/encrypted_messages/message_encrypter.h"
#include "components/metrics/metrics_state_manager.h"
#include "components/network_time/network_time_tracker.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/variations/field_trial_internals_utils.h"
#include "components/variations/pref_names.h"
#include "components/variations/proto/variations_seed.pb.h"
#include "components/variations/seed_response.h"
#include "components/variations/sticky_activation_manager.h"
#include "components/variations/variations_safe_seed_store_local_state.h"
#include "components/variations/variations_seed_simulator.h"
#include "components/variations/variations_switches.h"
#include "components/variations/variations_url_constants.h"
#include "components/version_info/channel.h"
#include "components/version_info/version_info.h"
#include "net/base/net_errors.h"
#include "net/base/url_util.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "url/gurl.h"

namespace variations {
namespace {

// Constants used for encrypting the if-none-match header if we are retrieving a
// seed over http.
const char kEncryptedMessageLabel[] = "chrome variations";

// TODO(crbug.com/41359527): Change this key to a unique VariationsService one,
// once the matching private key is changed server side.
// Key is used to encrypt headers in seed retrieval requests that happen over
// HTTP connections (when retrying after an unsuccessful HTTPS retrieval
// attempt).
const uint8_t kServerPublicKey[] = {
    0x51, 0xcc, 0x52, 0x67, 0x42, 0x47, 0x3b, 0x10, 0xe8, 0x63, 0x18,
    0x3c, 0x61, 0xa7, 0x96, 0x76, 0x86, 0x91, 0x40, 0x71, 0x39, 0x5f,
    0x31, 0x1a, 0x39, 0x5b, 0x76, 0xb1, 0x6b, 0x3d, 0x6a, 0x2b};

const uint32_t kServerPublicKeyVersion = 1;

// For the HTTP date headers, the resolution of the server time is 1 second.
const uint32_t kServerTimeResolutionInSeconds = 1;

// Whether the VariationsService should fetch the seed for testing.
bool g_should_fetch_for_testing = false;

// Returns a string that will be used for the value of the 'osname' URL param
// to the variations server.
std::string GetPlatformString() {
#if BUILDFLAG(IS_WIN)
  return "win";
#elif BUILDFLAG(IS_IOS)
  return "ios";
#elif BUILDFLAG(IS_MAC)
  return "mac";
#elif BUILDFLAG(IS_CHROMEOS)
  return "chromeos";
#elif BUILDFLAG(IS_ANDROID)
  return "android";
#elif BUILDFLAG(IS_FUCHSIA)
  return "fuchsia";
#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_BSD) || BUILDFLAG(IS_SOLARIS)
  // Default BSD and SOLARIS to Linux to not break those builds, although these
  // platforms are not officially supported by Chrome.
  return "linux";
#else
#error Unknown platform
#endif
}

// Gets the restrict parameter from either the passed override, the client or
// |policy_pref_service|.
std::string GetRestrictParameterValue(const std::string& restrict_mode_override,
                                      VariationsServiceClient* client,
                                      PrefService* policy_pref_service) {
  if (!restrict_mode_override.empty()) {
    return restrict_mode_override;
  }

  std::string parameter;
  if (client->OverridesRestrictParameter(&parameter) || !policy_pref_service) {
    return parameter;
  }

  return policy_pref_service->GetString(prefs::kVariationsRestrictParameter);
}

// Reported to UMA, keep in sync with enums.xml and don't renumber entries.
enum class ResourceRequestsAllowedState {
  kAllowed,
  kNotAllowed,
  kAllowedNotified,
  kNotAllowedEulaNotAccepted,
  kNotAllowedNetworkDown,
  kNotAllowedCommandLineDisabled,
  kNotAllowedNetworkStateNotInitialized,
  kMaxValue = kNotAllowedNetworkStateNotInitialized,
};

// Records UMA histogram with the current resource requests allowed state.
void RecordRequestsAllowedHistogram(ResourceRequestsAllowedState state) {
  base::UmaHistogramEnumeration("Variations.ResourceRequestsAllowed", state);
}

// Converts ResourceRequestAllowedNotifier::State to the corresponding
// ResourceRequestsAllowedState value.
ResourceRequestsAllowedState ResourceRequestStateToHistogramValue(
    web_resource::ResourceRequestAllowedNotifier::State state) {
  using web_resource::ResourceRequestAllowedNotifier;
  switch (state) {
    case ResourceRequestAllowedNotifier::DISALLOWED_EULA_NOT_ACCEPTED:
      return ResourceRequestsAllowedState::kNotAllowedEulaNotAccepted;
    case ResourceRequestAllowedNotifier::DISALLOWED_NETWORK_DOWN:
      return ResourceRequestsAllowedState::kNotAllowedNetworkDown;
    case ResourceRequestAllowedNotifier::DISALLOWED_COMMAND_LINE_DISABLED:
      return ResourceRequestsAllowedState::kNotAllowedCommandLineDisabled;
    case ResourceRequestAllowedNotifier::
        DISALLOWED_NETWORK_STATE_NOT_INITIALIZED:
      return ResourceRequestsAllowedState::
          kNotAllowedNetworkStateNotInitialized;
    case ResourceRequestAllowedNotifier::ALLOWED:
      return ResourceRequestsAllowedState::kAllowed;
  }
  NOTREACHED();
}

// Returns the header value for |name| from |headers| or an empty string_view if
// not set.
std::string_view GetHeaderValue(const net::HttpResponseHeaders* headers,
                                std::string_view name) {
  return headers->EnumerateHeader(nullptr, name).value_or(std::string_view());
}

// Returns the list of values for |name| from |headers|. If the header in not
// set, return an empty list.
std::vector<std::string> GetHeaderValuesList(
    const net::HttpResponseHeaders* headers,
    std::string_view name) {
  std::vector<std::string> values;
  size_t iter = 0;
  while (std::optional<std::string_view> value =
             headers->EnumerateHeader(&iter, name)) {
    values.emplace_back(*value);
  }
  return values;
}

// Looks for delta and gzip compression instance manipulation flags set by the
// server in |headers|. Checks the order of flags and presence of unknown
// instance manipulations. If successful, |is_delta_compressed| and
// |is_gzip_compressed| contain compression flags and true is returned.
bool GetInstanceManipulations(const net::HttpResponseHeaders* headers,
                              bool* is_delta_compressed,
                              bool* is_gzip_compressed) {
  std::vector<std::string> ims = GetHeaderValuesList(headers, "IM");
  const auto delta_im = std::ranges::find(ims, "x-bm");
  const auto gzip_im = std::ranges::find(ims, "gzip");
  *is_delta_compressed = delta_im != ims.end();
  *is_gzip_compressed = gzip_im != ims.end();

  // The IM field should not have anything but x-bm and gzip.
  size_t im_count =
      (*is_delta_compressed ? 1 : 0) + (*is_gzip_compressed ? 1 : 0);
  if (im_count != ims.size()) {
    DVLOG(1) << "Unrecognized instance manipulations in "
             << base::JoinString(ims, ",")
             << "; only x-bm and gzip are supported";
    return false;
  }

  // The IM field defines order in which instance manipulations were applied.
  // The client requests and supports gzip-compressed delta-compressed seeds,
  // but not vice versa.
  if (*is_delta_compressed && *is_gzip_compressed && delta_im > gzip_im) {
    DVLOG(1) << "Unsupported instance manipulations order: "
             << "requested x-bm,gzip but received gzip,x-bm";
    return false;
  }

  return true;
}

// Variations seed fetching is only enabled in official Chrome builds, if a URL
// is specified on the command line, and for testing.
bool IsFetchingEnabled() {
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableVariationsSeedFetch)) {
    return false;
  }
#else
  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kVariationsServerURL) &&
      !g_should_fetch_for_testing) {
    DVLOG(1)
        << "Not performing repeated fetching in unofficial build without --"
        << switches::kVariationsServerURL << " specified.";
    return false;
  }
#endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
  return true;
}

// Returns the already downloaded first run seed, and clear the seed from the
// native-side prefs. At this point, the seed has already been fetched from the
// native seed storage, so it's no longer needed there. This is done regardless
// if we fail or succeed below - since if we succeed, we're good to go and if we
// fail, we probably don't want to keep around the bad content anyway.
std::unique_ptr<SeedResponse> MaybeImportFirstRunSeed(
    VariationsServiceClient* client,
    PrefService* local_state) {
  if (!local_state->HasPrefPath(prefs::kVariationsSeedSignature)) {
    DVLOG(1) << "Importing first run seed from native preferences.";
    return client->TakeSeedFromNativeVariationsSeedStore();
  }
  return nullptr;
}

}  // namespace

#if BUILDFLAG(IS_CHROMEOS)
// This is a utility which syncs the policy-managed value of
// |prefs::kDeviceVariationsRestrictionsByPolicy| into
// |prefs::kVariationsRestrictionsByPolicy|.
// TODO(crbug.com/40121933): Remove this workaround and implement a better long
// term solution.
class DeviceVariationsRestrictionByPolicyApplicator {
 public:
  DeviceVariationsRestrictionByPolicyApplicator(
      PrefService* policy_pref_service)
      : policy_pref_service_(policy_pref_service) {
    DCHECK(policy_pref_service_);
    const PrefService::PrefInitializationStatus prefs_init_status =
        policy_pref_service_->GetAllPrefStoresInitializationStatus();
    if (prefs_init_status == PrefService::INITIALIZATION_STATUS_WAITING) {
      policy_pref_service_->AddPrefInitObserver(
          base::BindOnce(&DeviceVariationsRestrictionByPolicyApplicator::
                             OnPolicyPrefServiceInitialized,
                         weak_ptr_factory_.GetWeakPtr()));
      return;
    }
    OnPolicyPrefServiceInitialized(prefs_init_status ==
                                   PrefService::INITIALIZATION_STATUS_SUCCESS);
  }

  ~DeviceVariationsRestrictionByPolicyApplicator() = default;

  DeviceVariationsRestrictionByPolicyApplicator(
      const DeviceVariationsRestrictionByPolicyApplicator& other) = delete;
  DeviceVariationsRestrictionByPolicyApplicator& operator=(
      const DeviceVariationsRestrictionByPolicyApplicator& other) = delete;

 private:
  void OnPolicyPrefServiceInitialized(bool successful) {
    // If PrefService initialization was not successful, another component will
    // display an error message to the user.
    if (!successful) {
      return;
    }

    pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
    pref_change_registrar_->Init(policy_pref_service_);
    pref_change_registrar_->Add(
        prefs::kDeviceVariationsRestrictionsByPolicy,
        base::BindRepeating(&DeviceVariationsRestrictionByPolicyApplicator::
                                OnDevicePolicyChange,
                            weak_ptr_factory_.GetWeakPtr()));
    // Also process the initial value.
    OnDevicePolicyChange();
  }

  // Observes the changes in prefs::kDeviceVariationsRestrictionsByPolicy,
  // and saves and retrieve its local state value, then sets
  // prefs::kVariationsRestrictParameter with that new value. That's to
  // reflect the changes of chromeos policy into the user policy.
  // TODO(crbug.com/40121933): Remove that workaround, and make a better long
  // term solution.
  void OnDevicePolicyChange() {
    const std::string& device_policy =
        prefs::kDeviceVariationsRestrictionsByPolicy;
    const std::string& user_policy = prefs::kVariationsRestrictionsByPolicy;

    if (policy_pref_service_->IsManagedPreference(device_policy)) {
      const int device_value = policy_pref_service_->GetInteger(device_policy);
      policy_pref_service_->SetInteger(user_policy, device_value);
    } else {
      policy_pref_service_->ClearPref(user_policy);
    }
  }

  const raw_ptr<PrefService> policy_pref_service_;

  // Watch the changes of the variations prefs.
  std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;

  base::WeakPtrFactory<DeviceVariationsRestrictionByPolicyApplicator>
      weak_ptr_factory_{this};
};
#endif  // BUILDFLAG(IS_CHROMEOS)

VariationsService::VariationsService(
    std::unique_ptr<VariationsServiceClient> client,
    std::unique_ptr<web_resource::ResourceRequestAllowedNotifier> notifier,
    PrefService* local_state,
    metrics::MetricsStateManager* state_manager,
    const UIStringOverrider& ui_string_overrider)
    : client_(std::move(client)),
      local_state_(local_state),
      state_manager_(state_manager),
      policy_pref_service_(local_state),
      resource_request_allowed_notifier_(std::move(notifier)),
      safe_seed_manager_(local_state),
      // TODO(crbug.com/421912603): Verify whether all callers should pass
      // `true` here.
      entropy_providers_(state_manager_->CreateEntropyProviders(
          /*enable_limited_entropy_mode=*/true)),
      field_trial_creator_(
          client_.get(),
          std::make_unique<VariationsSeedStore>(
              local_state,
              MaybeImportFirstRunSeed(client_.get(), local_state),
              /*signature_verification_enabled=*/true,
              std::make_unique<VariationsSafeSeedStoreLocalState>(
                  local_state,
                  client_.get()->GetVariationsSeedFileDir(),
                  client_.get()->GetChannelForVariations(),
                  entropy_providers_.get()),
              client_.get()->GetChannelForVariations(),
              client_.get()->GetVariationsSeedFileDir(),
              entropy_providers_.get()),
          ui_string_overrider) {
  DCHECK(client_);
  DCHECK(resource_request_allowed_notifier_);

#if BUILDFLAG(IS_CHROMEOS)
  device_variations_restrictions_by_policy_applicator_ =
      std::make_unique<DeviceVariationsRestrictionByPolicyApplicator>(
          policy_pref_service_);
#endif
}

VariationsService::~VariationsService() = default;

void VariationsService::PerformPreMainMessageLoopStartup() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(field_trial_creator_.IsOverrideResourceMapEmpty());

  InitResourceRequestedAllowedNotifier();

// Android instead calls OnAppEnterForeground() which then calls
// StartRepeatedVariationsSeedFetch(). This is too early to do it on Android
// because at this point the |restrict_mode_| hasn't been set yet. See also
// the CHECK in SetRestrictMode().
#if !BUILDFLAG(IS_ANDROID)
  if (!IsFetchingEnabled()) {
    return;
  }

  StartRepeatedVariationsSeedFetch();
#endif  // !BUILDFLAG(IS_ANDROID)
}

bool VariationsService::EncryptString(const std::string& plaintext,
                                      std::string* encrypted) {
  encrypted_messages::EncryptedMessage encrypted_message;
  if (!encrypted_messages::EncryptSerializedMessage(
          kServerPublicKey, kServerPublicKeyVersion, kEncryptedMessageLabel,
          plaintext, &encrypted_message) ||
      !encrypted_message.SerializeToString(encrypted)) {
    return false;
  }
  return true;
}

void VariationsService::AddObserver(Observer* observer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  observer_list_.AddObserver(observer);
}

void VariationsService::RemoveObserver(Observer* observer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  observer_list_.RemoveObserver(observer);
}

void VariationsService::OnAppEnterForeground() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (!IsFetchingEnabled()) {
    return;
  }

  // On mobile platforms, initialize the fetch scheduler when we receive the
  // first app foreground notification.
  if (!request_scheduler_) {
    StartRepeatedVariationsSeedFetch();
  }
  request_scheduler_->OnAppEnterForeground();
}

void VariationsService::SetRestrictMode(const std::string& restrict_mode) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  // This should be called before the server URL has been computed. Note: This
  // uses a CHECK because this is relevant for the behavior in release official
  // builds that talk to the variations server - which don't enable DCHECKs.
  CHECK(variations_server_url_.is_empty());
  restrict_mode_ = restrict_mode;
}

bool VariationsService::IsLikelyDogfoodClient() const {
  // The param is typically only set for dogfood clients, though in principle it
  // could be set in other rare contexts as well.
  const std::string restrict_mode = GetRestrictParameterValue(
      restrict_mode_, client_.get(), policy_pref_service_);
  return !restrict_mode.empty();
}

void VariationsService::SetIsLikelyDogfoodClientForTesting(
    bool is_dogfood_client) {
  // Any non-empty value for the `restrict_mode_` is treated as a dogfood client
  // (see above).
  if (is_dogfood_client) {
    restrict_mode_ = "nonempty";
  } else {
    restrict_mode_ = std::string();
  }
}

GURL VariationsService::GetVariationsServerURL(HttpOptions http_options) {
  const bool secure = http_options == USE_HTTPS;
  const std::string restrict_mode = GetRestrictParameterValue(
      restrict_mode_, client_.get(), policy_pref_service_);

  // If there's a restrict mode, we don't want to fall back to HTTP to avoid
  // toggling restrict mode state.
  if (!secure && !restrict_mode.empty()) {
    return GURL();
  }

  std::string server_url_string(
      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
          secure ? switches::kVariationsServerURL
                 : switches::kVariationsInsecureServerURL));
  if (server_url_string.empty()) {
    server_url_string = secure ? kDefaultServerUrl : kDefaultInsecureServerUrl;
  }
  GURL server_url = GURL(server_url_string);
  if (!restrict_mode.empty()) {
    DCHECK(secure);
    server_url = net::AppendOrReplaceQueryParameter(server_url, "restrict",
                                                    restrict_mode);
  }
  server_url = net::AppendOrReplaceQueryParameter(
      server_url, "osname",
      osname_server_param_override_.empty() ? GetPlatformString()
                                            : osname_server_param_override_);

  // Add channel to the request URL.
  version_info::Channel channel = client_->GetChannelForVariations();
  if (channel != version_info::Channel::UNKNOWN) {
    server_url = net::AppendOrReplaceQueryParameter(
        server_url, "channel", version_info::GetChannelString(channel));
  }

  // Add milestone to the request URL.
  const std::string milestone = version_info::GetMajorVersionNumber();
  if (!milestone.empty()) {
    server_url =
        net::AppendOrReplaceQueryParameter(server_url, "milestone", milestone);
  }

  const std::string corpus =
      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
          switches::kVariationsSeedCorpus);
  if (!corpus.empty()) {
    server_url =
        net::AppendOrReplaceQueryParameter(server_url, "corpus", corpus);
  }

  DCHECK(server_url.is_valid());
  return server_url;
}

void VariationsService::EnsureLocaleEquals(const std::string& locale) {
#if BUILDFLAG(IS_CHROMEOS)
  // Chrome OS may switch language on the fly.
  return;
#else

#if BUILDFLAG(IS_ANDROID)
  // TODO(asvitkine): Speculative early return to silence CHECK failures on
  // Android, see crbug.com/912320.
  if (locale.empty()) {
    return;
  }
#endif

  // Uses a CHECK rather than a DCHECK to ensure that issues are caught since
  // problems in this area may only appear in the wild due to official builds
  // and end user machines.
  if (locale != field_trial_creator_.application_locale()) {
    // TODO(crbug.com/41430274): Report the two values in crash keys.
    static auto* lhs_key = base::debug::AllocateCrashKeyString(
        "mismatched_locale_lhs", base::debug::CrashKeySize::Size256);
    static auto* rhs_key = base::debug::AllocateCrashKeyString(
        "mismatched_locale_rhs", base::debug::CrashKeySize::Size256);
    base::debug::ScopedCrashKeyString scoped_lhs(lhs_key, locale);
    base::debug::ScopedCrashKeyString scoped_rhs(
        rhs_key, field_trial_creator_.application_locale());
    CHECK_EQ(locale, field_trial_creator_.application_locale());
  }
#endif
}

// static
std::string VariationsService::GetDefaultVariationsServerURLForTesting() {
  return kDefaultServerUrl;
}

// static
void VariationsService::RegisterPrefs(PrefRegistrySimple* registry) {
  SafeSeedManager::RegisterPrefs(registry);
  VariationsSeedStore::RegisterPrefs(registry);
  RegisterFieldTrialInternalsPrefs(*registry);
  StickyActivationManager::RegisterPrefs(*registry);

  registry->RegisterIntegerPref(
      prefs::kDeviceVariationsRestrictionsByPolicy,
      static_cast<int>(RestrictionPolicy::NO_RESTRICTIONS));
  registry->RegisterDictionaryPref(
      prefs::kVariationsGoogleGroups,
      static_cast<int>(RestrictionPolicy::NO_RESTRICTIONS));
  // This preference is used to override the variations country code which is
  // consistent across different chrome version.
  registry->RegisterStringPref(prefs::kVariationsPermanentOverriddenCountry,
                               std::string());
  // This preference keeps track of ChromeVariations enum policy which
  // allows the admin to restrict the set of variations applied.
  registry->RegisterIntegerPref(
      prefs::kVariationsRestrictionsByPolicy,
      static_cast<int>(RestrictionPolicy::NO_RESTRICTIONS));
  // This preference will only be written by the policy service, which will fill
  // it according to a value stored in the User Policy.
  registry->RegisterStringPref(prefs::kVariationsRestrictParameter,
                               std::string());
}

// static
void VariationsService::RegisterProfilePrefs(
    user_prefs::PrefRegistrySyncable* registry) {
  // This preference will only be written by the policy service, which will fill
  // it according to a value stored in the User Policy.
  registry->RegisterStringPref(prefs::kVariationsRestrictParameter,
                               std::string());
}

// static
std::unique_ptr<VariationsService> VariationsService::Create(
    std::unique_ptr<VariationsServiceClient> client,
    PrefService* local_state,
    metrics::MetricsStateManager* state_manager,
    const char* disable_network_switch,
    const UIStringOverrider& ui_string_overrider,
    web_resource::ResourceRequestAllowedNotifier::NetworkConnectionTrackerGetter
        network_connection_tracker_getter) {
  return base::WrapUnique(new VariationsService(
      std::move(client),
      std::make_unique<web_resource::ResourceRequestAllowedNotifier>(
          local_state, disable_network_switch,
          std::move(network_connection_tracker_getter)),
      local_state, state_manager, ui_string_overrider));
}

// static
void VariationsService::EnableFetchForTesting() {
  g_should_fetch_for_testing = true;
}

void VariationsService::DoActualFetch() {
  DoFetchFromURL(variations_server_url_, false);
}

const std::string& VariationsService::GetLatestSerialNumber() {
  return field_trial_creator_.seed_store()->GetLatestSerialNumber();
}

bool VariationsService::DoFetchFromURL(const GURL& url, bool is_http_retry) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(IsFetchingEnabled());

  safe_seed_manager_.RecordFetchStarted();

  // Normally, there shouldn't be a |pending_seed_request_| when this fires.
  // However it's not impossible - for example if Chrome was paused (e.g. in a
  // debugger or if the machine was suspended) and OnURLFetchComplete() hasn't
  // had a chance to run yet from the previous request. In this case, don't
  // start a new request and just let the previous one finish.
  if (pending_seed_request_) {
    return false;
  }

  last_request_was_http_retry_ = is_http_retry;

  net::NetworkTrafficAnnotationTag traffic_annotation =
      net::DefineNetworkTrafficAnnotation("chrome_variations_service", R"(
        semantics {
          sender: "Chrome Variations Service"
          description:
            "Retrieves the list of Google Chrome's Variations from the server, "
            "which will apply to the next Chrome session upon a restart."
          trigger:
            "Requests are made periodically while Google Chrome is running."
          data: "The operating system name."
          destination: GOOGLE_OWNED_SERVICE
        }
        policy {
          cookies_allowed: NO
          setting: "This feature cannot be disabled by settings."
          policy_exception_justification:
            "The ChromeVariations policy prevents Variations from applying, "
            "but Google Chrome still downloads Variations from the server "
            "periodically. This way, the downloaded Variations apply "
            "immediately on restart if you unset the ChromeVariations policy."
        })");
  auto resource_request = std::make_unique<network::ResourceRequest>();
  resource_request->url = url;
  resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
  std::string serial_number = GetLatestSerialNumber();
  if (!serial_number.empty()) {
    // Get the seed only if its serial number doesn't match what we have.
    // If the fetch is an HTTP retry, encrypt the If-None-Match header.
    if (is_http_retry) {
      if (!EncryptString(serial_number, &serial_number)) {
        return false;
      }
      serial_number = base::Base64Encode(serial_number);
    }
    resource_request->headers.SetHeader("If-None-Match", serial_number);
  }
  const bool enable_deltas =
      !serial_number.empty() && !delta_error_since_last_success_;
  // Tell the server that delta-compressed and gzipped seeds are supported.
  const char* supported_im = enable_deltas ? "x-bm,gzip" : "gzip";
  resource_request->headers.SetHeader("A-IM", supported_im);

  pending_seed_request_ = network::SimpleURLLoader::Create(
      std::move(resource_request), traffic_annotation);
  // Ensure our callback is called even with "304 Not Modified" responses.
  pending_seed_request_->SetAllowHttpErrorResults(true);
  pending_seed_request_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
      client_->GetURLLoaderFactory().get(),
      base::BindOnce(&VariationsService::OnSimpleLoaderComplete,
                     weak_ptr_factory_.GetWeakPtr()));

  const base::TimeTicks now = base::TimeTicks::Now();
  base::TimeDelta time_since_last_fetch;
  // Record a time delta of 0 (default value) if there was no previous fetch.
  if (!last_request_started_time_.is_null()) {
    time_since_last_fetch = now - last_request_started_time_;
  }
  base::UmaHistogramCustomCounts("Variations.TimeSinceLastFetchAttempt",
                                 time_since_last_fetch.InMinutes(), 1,
                                 base::Days(7).InMinutes(), 50);
  ++request_count_;
  last_request_started_time_ = now;
  delta_error_since_last_success_ = false;
  return true;
}

void VariationsService::StoreSeed(std::string seed_data,
                                  std::string seed_signature,
                                  std::string country_code,
                                  base::Time date_fetched,
                                  bool is_delta_compressed,
                                  bool is_gzip_compressed) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  base::OnceCallback<void(bool, VariationsSeed)> done_callback =
      base::BindOnce(&VariationsService::OnSeedStoreResult,
                     weak_ptr_factory_.GetWeakPtr(), is_delta_compressed);
  field_trial_creator_.seed_store()->StoreSeedData(
      std::move(done_callback), std::move(seed_data), std::move(seed_signature),
      std::move(country_code), date_fetched, is_delta_compressed,
      is_gzip_compressed,
      /*require_synchronous=*/false);
}

void VariationsService::OnSeedStoreResult(bool is_delta_compressed,
                                          bool store_success,
                                          VariationsSeed seed) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (!store_success && is_delta_compressed) {
    delta_error_since_last_success_ = true;
    // |request_scheduler_| will be null during unit tests.
    if (request_scheduler_) {
      request_scheduler_->ScheduleFetchShortly();
    }
  }

  if (store_success) {
    // When the new seed is stored, the active seed will be stored as the safe
    // seed.
    RecordSuccessfulFetchNewSeed();

    // Now, do simulation to determine if there are any kill-switches that were
    // activated by this seed.
    PerformSimulationWithVersion(seed, client_->GetVersionForSimulation());
  }
}

void VariationsService::InitResourceRequestedAllowedNotifier() {
  // ResourceRequestAllowedNotifier does not install an observer if there is no
  // NetworkChangeNotifier, which results in never being notified of changes to
  // network status.
  resource_request_allowed_notifier_->Init(this, /*leaky=*/false,
                                           /*wait_for_eula=*/false);
}

void VariationsService::StartRepeatedVariationsSeedFetch() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  // Initialize Variations server URLs.
  variations_server_url_ = GetVariationsServerURL(USE_HTTPS);
  insecure_variations_server_url_ = GetVariationsServerURL(USE_HTTP);

  DCHECK(!request_scheduler_);
  request_scheduler_.reset(VariationsRequestScheduler::Create(
      base::BindRepeating(&VariationsService::FetchVariationsSeed,
                          weak_ptr_factory_.GetWeakPtr()),
      local_state_));
  // Note that the act of starting the scheduler will start the fetch, if the
  // scheduler deems appropriate.
  request_scheduler_->Start();
}

void VariationsService::FetchVariationsSeed() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  const web_resource::ResourceRequestAllowedNotifier::State state =
      resource_request_allowed_notifier_->GetResourceRequestsAllowedState();
  RecordRequestsAllowedHistogram(ResourceRequestStateToHistogramValue(state));
  if (state != web_resource::ResourceRequestAllowedNotifier::ALLOWED) {
    DVLOG(1) << "Resource requests were not allowed. Waiting for notification.";
    return;
  }

  DoActualFetch();
}

void VariationsService::NotifyObservers(const SeedSimulationResult& result) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (result.kill_critical_group_change_count > 0) {
    for (auto& observer : observer_list_) {
      observer.OnExperimentChangesDetected(Observer::CRITICAL);
    }
  } else if (result.kill_best_effort_group_change_count > 0) {
    for (auto& observer : observer_list_) {
      observer.OnExperimentChangesDetected(Observer::BEST_EFFORT);
    }
  }
}

void VariationsService::OnSimpleLoaderComplete(
    std::optional<std::string> response_body) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  TRACE_EVENT0("browser", "VariationsService::OnSimpleLoaderComplete");

  const bool is_first_request = !initial_request_completed_;
  initial_request_completed_ = true;

  const base::TimeTicks now = base::TimeTicks::Now();
  if (is_first_request &&
      !local_state_->HasPrefPath(prefs::kVariationsSeedSignature)) {
    base::UmaHistogramTimes("Variations.SeedFetchTimeOnFirstRun",
                            now - last_request_started_time_);
  }

  const network::mojom::URLResponseHead* response_info =
      pending_seed_request_->ResponseInfo();
  const scoped_refptr<net::HttpResponseHeaders> headers =
      response_info ? response_info->headers : nullptr;
  const int response_code = headers ? headers->response_code() : -1;
  const int net_error = pending_seed_request_->NetError();
  const bool is_success = headers && response_body && (net_error == net::OK);

  pending_seed_request_.reset();
  if (last_request_was_http_retry_) {
    base::UmaHistogramSparse("Variations.SeedFetchResponseOrErrorCode.HTTP",
                             is_success ? response_code : net_error);
  } else {
    base::UmaHistogramSparse("Variations.SeedFetchResponseOrErrorCode",
                             is_success ? response_code : net_error);
  }
  if (!is_success) {
    DVLOG(1) << "Variations server request failed with error: " << net_error
             << ": " << net::ErrorToString(net_error);
    // It's common for the very first fetch attempt to fail (e.g. the network
    // may not yet be available). In such a case, try again soon, rather than
    // waiting the full time interval.
    // |request_scheduler_| will be null during unit tests.
    if (is_first_request && request_scheduler_) {
      request_scheduler_->ScheduleFetchShortly();
      return;
    }

    if (MaybeRetryOverHTTP()) {
      // If the retry was successfully started, return immediately,
      // OnSimpleLoaderComplete will be called again when the new fetch
      // finishes.
      return;
    }
  }

  // Return if there was a failure. Note that we check both |is_success| which
  // is set above and the response code. There could be a case where there's a
  // HTTP_OK response code but |is_success| is false, for example if the fetch
  // download was interrupted after having been started.
  if (!is_success || (response_code != net::HTTP_OK &&
                      response_code != net::HTTP_NOT_MODIFIED)) {
    DVLOG(1) << "Variations server request failed: is_success=" << is_success
             << " response_code=" << response_code
             << " net_error=" << net_error;
    return;
  }
  // At this point, |headers| and |response_body| should exist.
  DCHECK(headers);
  DCHECK(response_body);

  std::optional<base::Time> response_date = headers->GetDateValue();
  // If the seed was fetched securely, opportunistically update the network time
  // tracker with the headers time.
  if (response_date && !last_request_was_http_retry_) {
    DCHECK(!response_date->is_null());

    const base::TimeDelta latency = now - last_request_started_time_;
    client_->GetNetworkTimeTracker()->UpdateNetworkTime(
        response_date.value(), base::Seconds(kServerTimeResolutionInSeconds),
        latency, now);
  }

  if (response_code == net::HTTP_NOT_MODIFIED) {
    // TODO(crbug.com/420652919): Reject responses without a date.
    RecordSuccessfulFetchSeedNotModified(response_date.value_or(base::Time()));
    return;
  }

  // We're now handling the HTTP_OK success case.
  DCHECK_EQ(response_code, net::HTTP_OK);

  bool is_delta_compressed;
  bool is_gzip_compressed;
  if (!GetInstanceManipulations(headers.get(), &is_delta_compressed,
                                &is_gzip_compressed)) {
    // The header does not specify supported instance manipulations, unable to
    // process data. Details of errors were logged by GetInstanceManipulations.
    ReportUnsupportedSeedFormatError();
    return;
  }

  std::string_view signature =
      GetHeaderValue(headers.get(), "X-Seed-Signature");
  std::string_view country_code = GetHeaderValue(headers.get(), "X-Country");
  StoreSeed(std::move(*response_body), std::string(signature),
            std::string(country_code), response_date.value_or(base::Time()),
            is_delta_compressed, is_gzip_compressed);
}

bool VariationsService::MaybeRetryOverHTTP() {
  // If the current fetch attempt was over an HTTPS connection, retry the
  // fetch immediately over an HTTP connection. We only do this if an insecure
  // variations URL is set and its scheme is HTTP.
  if (!last_request_was_http_retry_ &&
      !insecure_variations_server_url_.is_empty() &&
      insecure_variations_server_url_.SchemeIs(url::kHttpScheme)) {
    return DoFetchFromURL(insecure_variations_server_url_, true);
  }
  return false;
}

void VariationsService::OnResourceRequestsAllowed() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  // Note that this only attempts to fetch the seed at most once per period
  // (kSeedFetchPeriodHours). This works because
  // |resource_request_allowed_notifier_| only calls this method if an
  // attempt was made earlier that fails (which implies that the period had
  // elapsed). After a successful attempt is made, the notifier will know not
  // to call this method again until another failed attempt occurs.
  RecordRequestsAllowedHistogram(
      ResourceRequestsAllowedState::kAllowedNotified);
  DVLOG(1) << "Retrying fetch.";
  DoActualFetch();

  // This service must have created a scheduler in order for this to be called.
  DCHECK(request_scheduler_);
  request_scheduler_->Reset();
}

void VariationsService::PerformSimulationWithVersion(
    const VariationsSeed& seed,
    const base::Version& version) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (!version.IsValid()) {
    return;
  }

  std::unique_ptr<ClientFilterableState> client_state =
      field_trial_creator_.GetClientFilterableStateForVersion(version);
  auto result = SimulateSeedStudies(seed, *client_state, *entropy_providers_);

  NotifyObservers(result);
}

bool VariationsService::CallMaybeRetryOverHTTPForTesting() {
  return MaybeRetryOverHTTP();
}

void VariationsService::RecordSuccessfulFetchNewSeed() {
  safe_seed_manager_.RecordSuccessfulFetch(field_trial_creator_.seed_store());
}

void VariationsService::RecordSuccessfulFetchSeedNotModified(
    base::Time response_date) {
  // Update the client-side fetch time to the current time.
  field_trial_creator_.seed_store()->RecordLastFetchTime(base::Time::Now());
  safe_seed_manager_.RecordSuccessfulFetch(field_trial_creator_.seed_store());

  // Update the seed date value in local state (used for expiry check on
  // next start up), since 304 is a successful response. Note that the
  // serial number included in the request is always that of the latest
  // seed, even when running in safe mode, so it's appropriate to always
  // modify the latest seed's date.
  field_trial_creator_.seed_store()->UpdateSeedDateAndLogDayChange(
      response_date);
}

VariationsSeedStore* VariationsService::GetSeedStoreForTesting() {
  return field_trial_creator_.seed_store();
}

base::Time VariationsService::GetLatestSeedFetchTime() {
  return field_trial_creator_.seed_store()->GetLatestSeedFetchTime();
}

void VariationsService::GetStoredSeedInfoForDebugging(
    base::OnceCallback<void(StoredSeedInfo)> done_callback,
    VariationsSeedStore::SeedType seed_type) {
  field_trial_creator_.seed_store()->GetStoredSeedInfoForDebugging(
      std::move(done_callback), seed_type);
}

std::unique_ptr<ClientFilterableState>
VariationsService::GetClientFilterableStateForVersion() {
  const base::Version current_version(version_info::GetVersionNumber());
  DCHECK(current_version.IsValid());
  return field_trial_creator_.GetClientFilterableStateForVersion(
      current_version);
}

std::string VariationsService::GetLatestCountry() const {
  return field_trial_creator_.GetLatestCountry();
}

bool VariationsService::SetUpFieldTrials(
    const std::vector<std::string>& variation_ids,
    const std::string& command_line_variation_ids,
    const std::vector<base::FeatureList::FeatureOverrideInfo>& extra_overrides,
    std::unique_ptr<base::FeatureList> feature_list,
    PlatformFieldTrials* platform_field_trials) {
  ForceTrialsAtStartup(*local_state_);

  return field_trial_creator_.SetUpFieldTrials(
      variation_ids, command_line_variation_ids, extra_overrides,
      std::move(feature_list), state_manager_, platform_field_trials,
      &safe_seed_manager_,
      /*add_entropy_source_to_variations_ids=*/true, *entropy_providers_);
}

void VariationsService::GetStudiesAvailableToForce(
    base::OnceCallback<void(std::vector<StudyGroupNames>)> done_callback) {
  field_trial_creator_.seed_store()->LoadSeed(
      base::IgnoreArgs<std::string, std::string>(base::BindOnce(
          &VariationsService::GetStudiesAvailableToForceFromSeed,
          weak_ptr_factory_.GetWeakPtr(), std::move(done_callback))));
}

SeedType VariationsService::GetSeedType() const {
  return field_trial_creator_.seed_type();
}

void VariationsService::OverrideCachedUIStrings() {
  field_trial_creator_.OverrideCachedUIStrings();
}

void VariationsService::CancelCurrentRequestForTesting() {
  pending_seed_request_.reset();
}

void VariationsService::StartRepeatedVariationsSeedFetchForTesting() {
  InitResourceRequestedAllowedNotifier();
  return StartRepeatedVariationsSeedFetch();
}

void VariationsService::OverridePlatform(
    Study::Platform platform,
    const std::string& osname_server_param_override) {
  field_trial_creator_.OverrideVariationsPlatform(platform);
  osname_server_param_override_ = osname_server_param_override;
}

std::string VariationsService::GetOverriddenPermanentCountry() const {
  return local_state_->GetString(prefs::kVariationsPermanentOverriddenCountry);
}

std::string VariationsService::GetStoredPermanentCountry() const {
  return field_trial_creator_.GetPermanentConsistencyCountry();
}

bool VariationsService::OverrideStoredPermanentCountry(
    const std::string& country_override) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  const std::string country_override_lowercase =
      base::ToLowerASCII(country_override);
  const std::string stored_country =
      local_state_->GetString(prefs::kVariationsPermanentOverriddenCountry);

  if (stored_country == country_override_lowercase) {
    return false;
  }

  field_trial_creator_.StoreVariationsOverriddenCountry(
      country_override_lowercase);
  return true;
}

void VariationsService::GetStudiesAvailableToForceFromSeed(
    base::OnceCallback<void(std::vector<StudyGroupNames>)> done_callback,
    bool success,
    VariationsSeed seed) {
  if (!success) {
    std::move(done_callback).Run({});
    return;
  }
  // TODO(crbug.com/41492213): chrome://field-trial-internals will not support
  // studies that are constrained to a layer with LIMITED entropy mode before
  // limited entropy randomization fully lands.
  auto entropy_providers = state_manager_->CreateEntropyProviders(
      /*enable_limited_entropy_mode=*/false);
  auto studies = variations::GetStudiesAvailableToForce(
      seed, *entropy_providers, *GetClientFilterableStateForVersion());
  std::move(done_callback).Run(std::move(studies));
}

}  // namespace variations
