chromium/base/metrics/field_trial.cc

// 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 "base/metrics/field_trial.h"

#include <algorithm>
#include <string_view>
#include <utility>

#include "base/auto_reset.h"
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/containers/span.h"
#include "base/debug/crash_logging.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/field_trial_param_associator.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
#include "base/process/memory.h"
#include "base/process/process_handle.h"
#include "base/process/process_info.h"
#include "base/rand_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"

#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"

#if BUILDFLAG(USE_BLINK)
#include "base/memory/shared_memory_switch.h"
#include "base/process/launch.h"
#endif

#if BUILDFLAG(IS_APPLE) && BUILDFLAG(USE_BLINK)
#include "base/mac/mach_port_rendezvous.h"
#endif

#if BUILDFLAG(IS_POSIX) && BUILDFLAG(USE_BLINK)
#include <unistd.h>  // For getppid().
#include "base/threading/platform_thread.h"
// On POSIX, the fd is shared using the mapping in GlobalDescriptors.
#include "base/posix/global_descriptors.h"
#endif

#if BUILDFLAG(IS_WIN)
#include <windows.h>
#endif

#if BUILDFLAG(IS_FUCHSIA)
#include <lib/zx/vmo.h>
#include <zircon/process.h>

#include "base/fuchsia/fuchsia_logging.h"
#endif

namespace base {

namespace {

#if BUILDFLAG(USE_BLINK)
SharedMemoryError;
#endif

// Define a separator character to use when creating a persistent form of an
// instance.  This is intended for use as a command line argument, passed to a
// second process to mimic our state (i.e., provide the same group name).
const char kPersistentStringSeparator =;  // Currently a slash.

// Define a marker character to be used as a prefix to a trial name on the
// command line which forces its activation.
const char kActivationMarker =;

// Constants for the field trial allocator.
const char kAllocatorName[] =;

// We allocate 256 KiB to hold all the field trial data. This should be enough,
// as most people use 3 - 25 KiB for field trials (as of 11/25/2016).
// This also doesn't allocate all 256 KiB at once -- the pages only get mapped
// to physical memory when they are touched. If the size of the allocated field
// trials does get larger than 256 KiB, then we will drop some field trials in
// child processes, leading to an inconsistent view between browser and child
// processes and possibly causing crashes (see crbug.com/661617).
const size_t kFieldTrialAllocationSize =;  // 256 KiB

#if BUILDFLAG(IS_APPLE) && BUILDFLAG(USE_BLINK)
constexpr MachPortsForRendezvous::key_type kFieldTrialRendezvousKey = 'fldt';
#endif

// Writes out string1 and then string2 to pickle.
void WriteStringPair(Pickle* pickle,
                     std::string_view string1,
                     std::string_view string2) {}

// Writes out the field trial's contents (via trial_state) to the pickle. The
// format of the pickle looks like:
// TrialName, GroupName, is_overridden, ParamKey1, ParamValue1, ParamKey2,
// ParamValue2, ... If there are no parameters, then it just ends at
// is_overridden.
void PickleFieldTrial(const FieldTrial::PickleState& trial_state,
                      Pickle* pickle) {}

// Returns the boundary value for comparing against the FieldTrial's added
// groups for a given |divisor| (total probability) and |entropy_value|.
FieldTrial::Probability GetGroupBoundaryValue(
    FieldTrial::Probability divisor,
    double entropy_value) {}

void OnOutOfMemory(size_t size) {}

void AppendFieldTrialGroupToString(bool activated,
                                   std::string_view trial_name,
                                   std::string_view group_name,
                                   std::string& field_trials_string) {}

}  // namespace

// statics
const int FieldTrial::kNotFinalized =;
const int FieldTrial::kDefaultGroupNumber =;
bool FieldTrial::enable_benchmarking_ =;

//------------------------------------------------------------------------------
// FieldTrial methods and members.

FieldTrial::EntropyProvider::~EntropyProvider() = default;

uint32_t FieldTrial::EntropyProvider::GetPseudorandomValue(
    uint32_t salt,
    uint32_t output_range) const {}

FieldTrial::PickleState::PickleState() = default;

FieldTrial::PickleState::PickleState(const PickleState& other) = default;

FieldTrial::PickleState::~PickleState() = default;

bool FieldTrial::FieldTrialEntry::GetState(std::string_view& trial_name,
                                           std::string_view& group_name,
                                           bool& overridden) const {}

bool FieldTrial::FieldTrialEntry::GetParams(
    std::map<std::string, std::string>* params) const {}

PickleIterator FieldTrial::FieldTrialEntry::GetPickleIterator() const {}

bool FieldTrial::FieldTrialEntry::ReadHeader(PickleIterator& iter,
                                             std::string_view& trial_name,
                                             std::string_view& group_name,
                                             bool& overridden) const {}

bool FieldTrial::FieldTrialEntry::ReadStringPair(
    PickleIterator* iter,
    std::string_view* trial_name,
    std::string_view* group_name) const {}

void FieldTrial::AppendGroup(const std::string& name,
                             Probability group_probability) {}

void FieldTrial::Activate() {}

const std::string& FieldTrial::group_name() {}

const std::string& FieldTrial::GetGroupNameWithoutActivation() {}

void FieldTrial::SetForced() {}

bool FieldTrial::IsOverridden() const {}

// static
void FieldTrial::EnableBenchmarking() {}

// static
FieldTrial* FieldTrial::CreateSimulatedFieldTrial(
    std::string_view trial_name,
    Probability total_probability,
    std::string_view default_group_name,
    double entropy_value) {}

// static
bool FieldTrial::ParseFieldTrialsString(std::string_view trials_string,
                                        bool override_trials,
                                        std::vector<State>& entries) {}

// static
std::string FieldTrial::BuildFieldTrialStateString(
    const std::vector<State>& states) {}

FieldTrial::FieldTrial(std::string_view trial_name,
                       const Probability total_probability,
                       std::string_view default_group_name,
                       double entropy_value,
                       bool is_low_anonymity,
                       bool is_overridden)
    :{}

FieldTrial::~FieldTrial() = default;

void FieldTrial::SetTrialRegistered() {}

void FieldTrial::SetGroupChoice(const std::string& group_name, int number) {}

void FieldTrial::FinalizeGroupChoice() {}

bool FieldTrial::GetActiveGroup(ActiveGroup* active_group) const {}

void FieldTrial::GetStateWhileLocked(PickleState* field_trial_state) {}

//------------------------------------------------------------------------------
// FieldTrialList methods and members.

// static
FieldTrialList* FieldTrialList::global_ =;

FieldTrialList::Observer::~Observer() = default;

FieldTrialList::FieldTrialList() {}

FieldTrialList::~FieldTrialList() {}

// static
FieldTrial* FieldTrialList::FactoryGetFieldTrial(
    std::string_view trial_name,
    FieldTrial::Probability total_probability,
    std::string_view default_group_name,
    const FieldTrial::EntropyProvider& entropy_provider,
    uint32_t randomization_seed,
    bool is_low_anonymity,
    bool is_overridden) {}

// static
FieldTrial* FieldTrialList::Find(std::string_view trial_name) {}

// static
std::string FieldTrialList::FindFullName(std::string_view trial_name) {}

// static
bool FieldTrialList::TrialExists(std::string_view trial_name) {}

// static
bool FieldTrialList::IsTrialActive(std::string_view trial_name) {}

// static
std::vector<FieldTrial::State> FieldTrialList::GetAllFieldTrialStates(
    PassKey<test::ScopedFeatureList>) {}

// static
void FieldTrialList::AllStatesToString(std::string* output) {}

// static
std::string FieldTrialList::AllParamsToString(EscapeDataFunc encode_data_func) {}

// static
void FieldTrialList::GetActiveFieldTrialGroups(
    FieldTrial::ActiveGroups* active_groups) {}

// static
std::set<std::string> FieldTrialList::GetActiveTrialsOfParentProcess() {}

// static
bool FieldTrialList::CreateTrialsFromString(const std::string& trials_string,
                                            bool override_trials) {}

// static
bool FieldTrialList::CreateTrialsFromFieldTrialStates(
    PassKey<test::ScopedFeatureList>,
    const std::vector<FieldTrial::State>& entries) {}

// static
void FieldTrialList::CreateTrialsInChildProcess(const CommandLine& cmd_line) {}

// static
void FieldTrialList::ApplyFeatureOverridesInChildProcess(
    FeatureList* feature_list) {}

#if BUILDFLAG(USE_BLINK)
// static
void FieldTrialList::PopulateLaunchOptionsWithFieldTrialState(
#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE)
    GlobalDescriptors::Key descriptor_key,
    ScopedFD& descriptor_to_share,
#endif
    CommandLine* command_line,
    LaunchOptions* launch_options) {}
#endif  // BUILDFLAG(USE_BLINK)

// static
ReadOnlySharedMemoryRegion
FieldTrialList::DuplicateFieldTrialSharedMemoryForTesting() {}

// static
FieldTrial* FieldTrialList::CreateFieldTrial(std::string_view name,
                                             std::string_view group_name,
                                             bool is_low_anonymity,
                                             bool is_overridden) {}

// static
bool FieldTrialList::AddObserver(Observer* observer) {}

// static
void FieldTrialList::RemoveObserver(Observer* observer) {}

// static
void FieldTrialList::NotifyFieldTrialGroupSelection(FieldTrial* field_trial) {}

// static
size_t FieldTrialList::GetFieldTrialCount() {}

// static
size_t FieldTrialList::GetRandomizedFieldTrialCount() {}

// static
bool FieldTrialList::GetParamsFromSharedMemory(
    FieldTrial* field_trial,
    std::map<std::string, std::string>* params) {}

// static
void FieldTrialList::ClearParamsFromSharedMemoryForTesting() {}

// static
void FieldTrialList::DumpAllFieldTrialsToPersistentAllocator(
    PersistentMemoryAllocator* allocator) {}

// static
std::vector<const FieldTrial::FieldTrialEntry*>
FieldTrialList::GetAllFieldTrialsFromPersistentAllocator(
    PersistentMemoryAllocator const& allocator) {}

// static
FieldTrialList* FieldTrialList::GetInstance() {}

// static
FieldTrialList* FieldTrialList::ResetInstance() {}

// static
FieldTrialList* FieldTrialList::BackupInstanceForTesting() {}

// static
void FieldTrialList::RestoreInstanceForTesting(FieldTrialList* instance) {}

#if BUILDFLAG(USE_BLINK)

// static
SharedMemoryError FieldTrialList::CreateTrialsFromSwitchValue(
    const std::string& switch_value) {}

#endif  // BUILDFLAG(USE_BLINK)

// static
bool FieldTrialList::CreateTrialsFromSharedMemoryRegion(
    const ReadOnlySharedMemoryRegion& shm_region) {}

// static
bool FieldTrialList::CreateTrialsFromSharedMemoryMapping(
    ReadOnlySharedMemoryMapping shm_mapping) {}

// static
void FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded() {}

// static
void FieldTrialList::AddToAllocatorWhileLocked(
    PersistentMemoryAllocator* allocator,
    FieldTrial* field_trial) {}

// static
void FieldTrialList::ActivateFieldTrialEntryWhileLocked(
    FieldTrial* field_trial) {}

FieldTrial* FieldTrialList::PreLockedFind(std::string_view name) {}

// static
void FieldTrialList::Register(FieldTrial* trial, bool is_randomized_trial) {}

// static
FieldTrialList::RegistrationMap FieldTrialList::GetRegisteredTrials() {}

// static
bool FieldTrialList::CreateTrialsFromFieldTrialStatesInternal(
    const std::vector<FieldTrial::State>& entries) {}

// static
void FieldTrialList::GetActiveFieldTrialGroupsInternal(
    FieldTrial::ActiveGroups* active_groups,
    bool include_low_anonymity) {}

// static
bool FieldTrialList::AddObserverInternal(Observer* observer,
                                         bool include_low_anonymity) {}

// static
void FieldTrialList::RemoveObserverInternal(Observer* observer,
                                            bool include_low_anonymity) {}

}  // namespace base