diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/components/variations/synthetic_trial_registry.cc | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/components/variations/synthetic_trial_registry.cc')
-rw-r--r-- | chromium/components/variations/synthetic_trial_registry.cc | 142 |
1 files changed, 114 insertions, 28 deletions
diff --git a/chromium/components/variations/synthetic_trial_registry.cc b/chromium/components/variations/synthetic_trial_registry.cc index ea07f680fbd..c0afd33c474 100644 --- a/chromium/components/variations/synthetic_trial_registry.cc +++ b/chromium/components/variations/synthetic_trial_registry.cc @@ -4,11 +4,32 @@ #include "components/variations/synthetic_trial_registry.h" +#include <algorithm> + +#include "base/metrics/histogram_functions.h" #include "base/stl_util.h" +#include "base/strings/string_number_conversions.h" +#include "components/variations/hashing.h" +#include "components/variations/variations_associated_data.h" namespace variations { +namespace internal { + +const base::Feature kExternalExperimentAllowlist{ + "ExternalExperimentAllowlist", base::FEATURE_ENABLED_BY_DEFAULT}; + +} // namespace internal -SyntheticTrialRegistry::SyntheticTrialRegistry() = default; +SyntheticTrialRegistry::SyntheticTrialRegistry( + bool enable_external_experiment_allowlist) + : enable_external_experiment_allowlist_( + enable_external_experiment_allowlist && + base::FeatureList::IsEnabled( + internal::kExternalExperimentAllowlist)) {} + +SyntheticTrialRegistry::SyntheticTrialRegistry() + : enable_external_experiment_allowlist_(base::FeatureList::IsEnabled( + internal::kExternalExperimentAllowlist)) {} SyntheticTrialRegistry::~SyntheticTrialRegistry() = default; void SyntheticTrialRegistry::AddSyntheticTrialObserver( @@ -23,13 +44,78 @@ void SyntheticTrialRegistry::RemoveSyntheticTrialObserver( synthetic_trial_observer_list_.RemoveObserver(observer); } +void SyntheticTrialRegistry::RegisterExternalExperiments( + const std::string& fallback_study_name, + const std::vector<int>& experiment_ids, + SyntheticTrialRegistry::OverrideMode mode) { + DCHECK(!fallback_study_name.empty()); + + base::FieldTrialParams params; + if (enable_external_experiment_allowlist_ && + !GetFieldTrialParamsByFeature(internal::kExternalExperimentAllowlist, + ¶ms)) { + return; + } + + // When overriding previous external experiments, remove them now. + if (mode == kOverrideExistingIds) { + auto is_external = [](const SyntheticTrialGroup& group) { + return group.is_external; + }; + base::EraseIf(synthetic_trial_groups_, is_external); + } + + const base::TimeTicks start_time = base::TimeTicks::Now(); + int trials_added = 0; + for (int experiment_id : experiment_ids) { + const std::string experiment_id_str = base::NumberToString(experiment_id); + const base::StringPiece study_name = + GetStudyNameForExpId(fallback_study_name, params, experiment_id_str); + if (study_name.empty()) + continue; + + const uint32_t trial_hash = HashName(study_name); + // If existing ids shouldn't be overridden, skip entries whose study names + // are already registered. + if (mode == kDoNotOverrideExistingIds) { + auto matches_trial = [trial_hash](const SyntheticTrialGroup& group) { + return group.id.name == trial_hash; + }; + const auto& groups = synthetic_trial_groups_; + if (std::any_of(groups.begin(), groups.end(), matches_trial)) { + continue; + } + } + + const uint32_t group_hash = HashName(experiment_id_str); + + // Since external experiments are not based on Chrome's low entropy source, + // they are only sent to Google web properties for signed-in users to make + // sure they couldn't be used to identify a user that's not signed-in. + AssociateGoogleVariationIDForceHashes( + GOOGLE_WEB_PROPERTIES_SIGNED_IN, {trial_hash, group_hash}, + static_cast<VariationID>(experiment_id)); + SyntheticTrialGroup entry(trial_hash, group_hash); + entry.start_time = start_time; + entry.is_external = true; + synthetic_trial_groups_.push_back(entry); + trials_added++; + } + + base::UmaHistogramCounts100("UMA.ExternalExperiment.GroupCount", + trials_added); + + if (trials_added > 0) + NotifySyntheticTrialObservers(); +} + void SyntheticTrialRegistry::RegisterSyntheticFieldTrial( const SyntheticTrialGroup& trial) { - for (size_t i = 0; i < synthetic_trial_groups_.size(); ++i) { - if (synthetic_trial_groups_[i].id.name == trial.id.name) { - if (synthetic_trial_groups_[i].id.group != trial.id.group) { - synthetic_trial_groups_[i].id.group = trial.id.group; - synthetic_trial_groups_[i].start_time = base::TimeTicks::Now(); + for (auto& entry : synthetic_trial_groups_) { + if (entry.id.name == trial.id.name) { + if (entry.id.group != trial.id.group) { + entry.id.group = trial.id.group; + entry.start_time = base::TimeTicks::Now(); NotifySyntheticTrialObservers(); } return; @@ -42,26 +128,26 @@ void SyntheticTrialRegistry::RegisterSyntheticFieldTrial( NotifySyntheticTrialObservers(); } -void SyntheticTrialRegistry::RegisterSyntheticMultiGroupFieldTrial( - uint32_t trial_name_hash, - const std::vector<uint32_t>& group_name_hashes) { - auto has_same_trial_name = [trial_name_hash](const SyntheticTrialGroup& x) { - return x.id.name == trial_name_hash; - }; - base::EraseIf(synthetic_trial_groups_, has_same_trial_name); +base::StringPiece SyntheticTrialRegistry::GetStudyNameForExpId( + const std::string& fallback_study_name, + const base::FieldTrialParams& params, + const std::string& experiment_id) { + if (!enable_external_experiment_allowlist_) + return fallback_study_name; - if (group_name_hashes.empty()) - return; + const auto it = params.find(experiment_id); + if (it == params.end()) + return base::StringPiece(); - SyntheticTrialGroup trial_group(trial_name_hash, group_name_hashes[0]); - trial_group.start_time = base::TimeTicks::Now(); - for (uint32_t group_name_hash : group_name_hashes) { - // Note: Adding the trial group will copy it, so this re-uses the same - // |trial_group| struct for convenience (e.g. so start_time's all match). - trial_group.id.group = group_name_hash; - synthetic_trial_groups_.push_back(trial_group); - } - NotifySyntheticTrialObservers(); + // To support additional parameters being passed, besides the study name, + // truncate the study name at the first ',' character. + // For example, for an entry like {"1234": "StudyName,FOO"}, we only want the + // "StudyName" part. This allows adding support for additional things like FOO + // in the future without backwards compatibility problems. + const size_t comma_pos = it->second.find(','); + const size_t truncate_pos = + (comma_pos == std::string::npos ? it->second.length() : comma_pos); + return base::StringPiece(it->second.data(), truncate_pos); } void SyntheticTrialRegistry::NotifySyntheticTrialObservers() { @@ -72,12 +158,12 @@ void SyntheticTrialRegistry::NotifySyntheticTrialObservers() { void SyntheticTrialRegistry::GetSyntheticFieldTrialsOlderThan( base::TimeTicks time, - std::vector<ActiveGroupId>* synthetic_trials) { + std::vector<ActiveGroupId>* synthetic_trials) const { DCHECK(synthetic_trials); synthetic_trials->clear(); - for (size_t i = 0; i < synthetic_trial_groups_.size(); ++i) { - if (synthetic_trial_groups_[i].start_time <= time) - synthetic_trials->push_back(synthetic_trial_groups_[i].id); + for (const auto& entry : synthetic_trial_groups_) { + if (entry.start_time <= time) + synthetic_trials->push_back(entry.id); } } |