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

import("//build/buildflag_header.gni")
import("//build/config/cast.gni")
import("//mojo/public/tools/bindings/mojom.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
import("//testing/test.gni")
import("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni")

mojom("variations_mojom") {
  generate_java = true
  sources = [ "variations.mojom" ]
}

if (is_android) {
  import("//build/config/android/rules.gni")
}

large_variation_key_size_enabled = is_castos || is_cast_android

buildflag_header("buildflags") {
  header = "buildflags.h"
  flags = [ "LARGE_VARIATION_KEY_SIZE=$large_variation_key_size_enabled" ]
}

component("variations_features") {
  output_name = "variations_features"

  defines = [ "IS_VARIATIONS_FEATURES_IMPL" ]

  sources = [
    "variations_features.cc",
    "variations_features.h",
  ]

  deps = [ "//base" ]
}

component("variations") {
  sources = [
    "active_field_trials.cc",
    "active_field_trials.h",
    "child_process_field_trial_syncer.cc",
    "child_process_field_trial_syncer.h",
    "client_filterable_state.cc",
    "client_filterable_state.h",
    "entropy_provider.cc",
    "entropy_provider.h",
    "fake_crash.cc",
    "fake_crash.h",
    "feature_overrides.cc",
    "feature_overrides.h",
    "field_trial_internals_utils.cc",
    "field_trial_internals_utils.h",
    "hashing.cc",
    "hashing.h",
    "limited_layer_entropy_cost_tracker.cc",
    "limited_layer_entropy_cost_tracker.h",
    "metrics.cc",
    "metrics.h",
    "platform_field_trials.h",
    "pref_names.h",
    "processed_study.cc",
    "processed_study.h",
    "seed_reader_writer.cc",
    "seed_reader_writer.h",
    "seed_response.cc",
    "seed_response.h",
    "sticky_activation_manager.cc",
    "sticky_activation_manager.h",
    "study_filtering.cc",
    "study_filtering.h",
    "synthetic_trial_registry.cc",
    "synthetic_trial_registry.h",
    "synthetic_trials.cc",
    "synthetic_trials.h",
    "synthetic_trials_active_group_id_provider.cc",
    "synthetic_trials_active_group_id_provider.h",
    "variations_associated_data.cc",
    "variations_associated_data.h",
    "variations_client.h",
    "variations_crash_keys.cc",
    "variations_crash_keys.h",
    "variations_ids_provider.cc",
    "variations_ids_provider.h",
    "variations_layers.cc",
    "variations_layers.h",
    "variations_murmur_hash.cc",
    "variations_murmur_hash.h",
    "variations_request_scheduler.cc",
    "variations_request_scheduler.h",
    "variations_safe_seed_store.cc",
    "variations_safe_seed_store.h",
    "variations_seed_processor.cc",
    "variations_seed_processor.h",
    "variations_seed_simulator.cc",
    "variations_seed_simulator.h",
    "variations_seed_store.cc",
    "variations_seed_store.h",
    "variations_switches.cc",
    "variations_switches.h",
    "variations_url_constants.cc",
    "variations_url_constants.h",
  ]

  # Needed for exporting functions (because the target type is a component).
  defines = [ "IS_VARIATIONS_IMPL" ]

  if (is_android || is_ios) {
    sources += [
      "variations_request_scheduler_mobile.cc",
      "variations_request_scheduler_mobile.h",
    ]
  }

  if (is_chromeos) {
    sources += [
      "variations_crash_keys_chromeos.cc",
      "variations_crash_keys_chromeos.h",
    ]
  }

  public_deps = [
    ":variations_features",
    "proto",
    "proto:client_variations_proto",
    "//base",
  ]

  deps = [
    ":buildflags",
    ":variations_mojom",
    "proto",
    "//base:build_time",
    "//components/crash/core/common:crash_key",
    "//components/prefs",
    "//components/version_info",
    "//crypto",
    "//third_party/protobuf:protobuf_lite",
    "//third_party/zlib/google:compression_utils",
  ]

  if (!is_android) {
    # ZSTD is not supported on Android due to binary size increase. See
    # crbug.com/40196713.
    deps += [
      "//third_party/zstd:compress",
      "//third_party/zstd:decompress",
    ]
  }

  if (is_android) {
    sources += [
      "android/variations_seed_bridge.cc",
      "android/variations_seed_bridge.h",
      "variations_crash_keys_android.cc",
      "variations_crash_keys_android.h",
    ]
    deps += [
      "//components/crash/android:anr_build_id_provider",
      "//components/crash/android:anr_collector_jni_headers",
      "//components/variations/android:variations_seed_jni",
    ]
  }
}

if (is_android) {
  static_library("variations_associated_data") {
    sources = [ "android/variations_associated_data_android.cc" ]
    deps = [
      ":variations",
      "//components/variations/android:variations_data_jni",
      "//components/variations/net",
    ]
  }

  java_cpp_strings("java_switches_srcjar") {
    # External code should depend on ":variations_java" instead.
    visibility = [ ":*" ]
    sources = [ "variations_switches.cc" ]
    class_name = "org.chromium.components.variations.VariationsSwitches"
  }

  android_library("variations_java") {
    srcjar_deps = [
      ":java_switches_srcjar",
      ":variations_enum_srcjar",
    ]
    deps = [ "//third_party/androidx:androidx_annotation_annotation_java" ]
  }

  java_cpp_enum("variations_enum_srcjar") {
    # External code should depend on ":variations_java" instead.
    visibility = [ ":*" ]
    sources = [
      "metrics.h",
      "synthetic_trials.h",
    ]
  }
}

static_library("test_support") {
  testonly = true
  sources = [
    "scoped_variations_ids_provider.cc",
    "scoped_variations_ids_provider.h",
    "service/test_variations_service.cc",
    "service/test_variations_service.h",
    "variations_test_utils.cc",
    "variations_test_utils.h",
  ]

  public_deps = [
    ":variations",
    ":variations_mojom",
  ]

  deps = [
    "field_trial_config",
    "proto",
    "proto:client_variations_proto",
    "//base/test:test_support",
    "//components/metrics",
    "//components/prefs",
    "//components/variations/service",
    "//components/web_resource:test_support",
    "//services/network:test_support",
    "//services/network/public/cpp",
    "//third_party/zlib/google:compression_utils",
  ]
}

source_set("unit_tests") {
  testonly = true
  sources = [
    "active_field_trials_unittest.cc",
    "antishuffle_unittest.cc",
    "child_process_field_trial_syncer_unittest.cc",
    "client_filterable_state_unittest.cc",
    "entropy_provider_unittest.cc",
    "field_trial_internals_utils_unittest.cc",
    "hashing_unittest.cc",
    "limited_layer_entropy_cost_tracker_unittest.cc",
    "net/variations_command_line_unittest.cc",
    "net/variations_http_headers_unittest.cc",
    "processed_study_unittest.cc",
    "seed_reader_writer_unittest.cc",
    "simulate_for_crosstalk_unittest.cc",
    "sticky_activation_manager_unittest.cc",
    "study_filtering_unittest.cc",
    "synthetic_trial_registry_unittest.cc",
    "uniformity_unittest.cc",
    "variations_associated_data_unittest.cc",
    "variations_ids_provider_unittest.cc",
    "variations_layers_unittest.cc",
    "variations_murmur_hash_unittest.cc",
    "variations_request_scheduler_unittest.cc",
    "variations_seed_processor_unittest.cc",
    "variations_seed_simulator_unittest.cc",
    "variations_seed_store_unittest.cc",
    "variations_test_utils_unittest.cc",
  ]

  if (is_android || is_ios) {
    sources += [ "variations_request_scheduler_mobile_unittest.cc" ]
  }
  if (is_chromeos) {
    sources += [ "variations_crash_keys_chromeos_unittest.cc" ]
  }

  # This test uses crash_reporter::GetCrashKeyValue(), which in a component
  # build returns the crash keys in the unit-test, not the "variations"
  # target. The test verifies the keys in the "variations" target, not the
  # test. As such, it fails in component builds.
  # TODO(crbug.com/40172607): Enable this unittest for is_fuchsia when crash
  # keys are supported on Fuchsia.
  if (!is_component_build && !is_fuchsia) {
    sources += [ "variations_crash_keys_unittest.cc" ]
  }

  deps = [
    ":test_support",
    ":variations",
    ":variations_features",
    ":variations_mojom",
    "net",
    "proto",
    "//base:build_time",
    "//base/test:test_support",
    "//components/crash/core/common:crash_key",
    "//components/metrics",
    "//components/prefs:test_support",
    "//components/variations/field_trial_config",
    "//components/variations/service",
    "//net:test_support",
    "//net/traffic_annotation:test_support",
    "//services/network:test_support",
    "//services/network/public/cpp:cpp_base",
    "//testing/gmock",
    "//testing/gtest",
    "//third_party/smhasher:murmurhash3",
    "//third_party/zlib/google:compression_utils",
    "//url",
  ]

  if (use_blink) {
    deps += [ "//third_party/blink/public/common" ]
  }
}

# Convenience testing target
test("variations_unittests") {
  sources = [ "//components/test/run_all_unittests.cc" ]
  deps = [
    ":unit_tests",
    "//components/test:test_support",
    "//components/variations/field_trial_config:unit_tests",
    "//components/variations/service:unit_tests",
  ]
}

if (use_fuzzing_engine_with_lpm) {
  fuzzable_proto_library("test_cases_proto") {
    sources = [ "fuzzers/create_trials_from_seed_test_case.proto" ]
    deps = [ "//components/variations/proto" ]
    proto_in_dir = "//"
  }

  fuzzer_test("create_trial_from_study_fuzzer") {
    sources = [ "fuzzers/create_trial_from_study_fuzzer.cc" ]
    deps = [
      ":variations",
      "proto",
      "proto:proto_fuzzable",
      "//base/test:test_support",
      "//third_party/libprotobuf-mutator",
    ]

    # TODO(crbug.com/505034799): Migrate to FUZZ_TEST.
    is_fuzztest_compatible = false
  }

  fuzzer_test("create_trials_from_seed_fuzzer") {
    sources = [ "fuzzers/create_trials_from_seed_fuzzer.cc" ]
    deps = [
      ":test_support",
      ":variations",
      "proto",
      "proto:proto_fuzzable",
      "//base/test:test_support",
      "//third_party/libprotobuf-mutator",
    ]

    # TODO(crbug.com/505034799): Migrate to FUZZ_TEST.
    is_fuzztest_compatible = false
  }

  fuzzer_test("create_trials_from_seed_v2_fuzzer") {
    sources = [ "fuzzers/create_trials_from_seed_fuzzer_v2.cc" ]
    deps = [
      ":test_cases_proto",
      ":test_cases_proto_fuzzable",
      ":test_support",
      ":variations",
      "proto",
      "proto:proto_fuzzable",
      "//base/test:test_support",
      "//components/metrics",
      "//components/metrics:test_support",
      "//components/prefs:test_support",
      "//components/variations/service",
      "//third_party/libprotobuf-mutator",
    ]
    if (is_android) {
      # Provides org.chromium.components.metrics.LowEntropySource.
      deps += [ "//components/metrics:metrics_java" ]
    }
    seed_corpus = "fuzzers/testcases/create_trials_from_seed/"
  }
}
