summaryrefslogtreecommitdiff
path: root/chromium/components/variations/synthetic_trial_registry.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/components/variations/synthetic_trial_registry.cc
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-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.cc142
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,
+ &params)) {
+ 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);
}
}