summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorasvitkine <asvitkine@chromium.org>2014-10-31 14:59:57 -0700
committerCommit bot <commit-bot@chromium.org>2014-10-31 22:00:18 +0000
commite0dbdbe3aa7dce4dda9e9acb20325d8476003fa8 (patch)
tree538bbae51dc2dd71e8a8c50755cbeb7d0da67c43
parent403be2a2a9f71ef7be26dd083d058732577a7ad3 (diff)
downloadchromium_src-e0dbdbe3aa7dce4dda9e9acb20325d8476003fa8.zip
chromium_src-e0dbdbe3aa7dce4dda9e9acb20325d8476003fa8.tar.gz
chromium_src-e0dbdbe3aa7dce4dda9e9acb20325d8476003fa8.tar.bz2
Plumbing for variations headers from synthetic field trials.
BUG=428055 Review URL: https://codereview.chromium.org/688973004 Cr-Commit-Position: refs/heads/master@{#302331}
-rw-r--r--chrome/browser/chrome_browser_main.cc1
-rw-r--r--components/metrics/metrics_service.cc19
-rw-r--r--components/metrics/metrics_service.h24
-rw-r--r--components/variations.gypi1
-rw-r--r--components/variations/net/BUILD.gn1
-rw-r--r--components/variations/net/DEPS1
-rw-r--r--components/variations/net/variations_http_header_provider.cc47
-rw-r--r--components/variations/net/variations_http_header_provider.h14
-rw-r--r--components/variations/variations_associated_data.cc18
-rw-r--r--components/variations/variations_associated_data.h10
10 files changed, 112 insertions, 24 deletions
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 6ab5340..48e78ea 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -623,6 +623,7 @@ void ChromeBrowserMainParts::SetupMetricsAndFieldTrials() {
command_line->GetSwitchValueASCII(switches::kForceVariationIds));
CHECK(result) << "Invalid --" << switches::kForceVariationIds
<< " list specified.";
+ metrics->AddSyntheticTrialObserver(provider);
}
chrome_variations::VariationsService* variations_service =
browser_process_->variations_service();
diff --git a/components/metrics/metrics_service.cc b/components/metrics/metrics_service.cc
index 4db3bb5..4fa2e75 100644
--- a/components/metrics/metrics_service.cc
+++ b/components/metrics/metrics_service.cc
@@ -1138,6 +1138,18 @@ bool MetricsService::UmaMetricsProperlyShutdown() {
return clean_shutdown_status_ == CLEANLY_SHUTDOWN;
}
+void MetricsService::AddSyntheticTrialObserver(
+ SyntheticTrialObserver* observer) {
+ synthetic_trial_observer_list_.AddObserver(observer);
+ if (!synthetic_trial_groups_.empty())
+ observer->OnSyntheticTrialsChanged(synthetic_trial_groups_);
+}
+
+void MetricsService::RemoveSyntheticTrialObserver(
+ SyntheticTrialObserver* observer) {
+ synthetic_trial_observer_list_.RemoveObserver(observer);
+}
+
void MetricsService::RegisterSyntheticFieldTrial(
const SyntheticTrialGroup& trial) {
for (size_t i = 0; i < synthetic_trial_groups_.size(); ++i) {
@@ -1145,6 +1157,7 @@ void MetricsService::RegisterSyntheticFieldTrial(
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();
+ NotifySyntheticTrialObservers();
}
return;
}
@@ -1153,6 +1166,7 @@ void MetricsService::RegisterSyntheticFieldTrial(
SyntheticTrialGroup trial_group = trial;
trial_group.start_time = base::TimeTicks::Now();
synthetic_trial_groups_.push_back(trial_group);
+ NotifySyntheticTrialObservers();
}
void MetricsService::RegisterMetricsProvider(
@@ -1166,6 +1180,11 @@ void MetricsService::CheckForClonedInstall(
state_manager_->CheckForClonedInstall(task_runner);
}
+void MetricsService::NotifySyntheticTrialObservers() {
+ FOR_EACH_OBSERVER(SyntheticTrialObserver, synthetic_trial_observer_list_,
+ OnSyntheticTrialsChanged(synthetic_trial_groups_));
+}
+
void MetricsService::GetCurrentSyntheticFieldTrials(
std::vector<variations::ActiveGroupId>* synthetic_trials) {
DCHECK(synthetic_trials);
diff --git a/components/metrics/metrics_service.h b/components/metrics/metrics_service.h
index eae44f3..19794ea 100644
--- a/components/metrics/metrics_service.h
+++ b/components/metrics/metrics_service.h
@@ -21,6 +21,7 @@
#include "base/metrics/histogram_flattener.h"
#include "base/metrics/histogram_snapshot_manager.h"
#include "base/metrics/user_metrics.h"
+#include "base/observer_list.h"
#include "base/time/time.h"
#include "components/metrics/clean_exit_beacon.h"
#include "components/metrics/metrics_log.h"
@@ -76,6 +77,17 @@ struct SyntheticTrialGroup {
SyntheticTrialGroup(uint32 trial, uint32 group);
};
+// Interface class to observe changes to synthetic trials in MetricsService.
+class SyntheticTrialObserver {
+ public:
+ // Called when the list of synthetic field trial groups has changed.
+ virtual void OnSyntheticTrialsChanged(
+ const std::vector<SyntheticTrialGroup>& groups) = 0;
+
+ protected:
+ virtual ~SyntheticTrialObserver() {}
+};
+
// See metrics_service.cc for a detailed description.
class MetricsService : public base::HistogramFlattener {
public:
@@ -211,6 +223,12 @@ class MetricsService : public base::HistogramFlattener {
// To use this method, SyntheticTrialGroup should friend your class.
void RegisterSyntheticFieldTrial(const SyntheticTrialGroup& trial_group);
+ // Adds an observer to be notified when the synthetic trials list changes.
+ void AddSyntheticTrialObserver(SyntheticTrialObserver* observer);
+
+ // Removes an existing observer of synthetic trials list changes.
+ void RemoveSyntheticTrialObserver(SyntheticTrialObserver* observer);
+
// Register the specified |provider| to provide additional metrics into the
// UMA log. Should be called during MetricsService initialization only.
void RegisterMetricsProvider(scoped_ptr<MetricsProvider> provider);
@@ -358,6 +376,9 @@ class MetricsService : public base::HistogramFlattener {
// Sets the value of the specified path in prefs and schedules a save.
void RecordBooleanPrefValue(const char* path, bool value);
+ // Notifies observers on a synthetic trial list change.
+ void NotifySyntheticTrialObservers();
+
// Returns a list of synthetic field trials that were active for the entire
// duration of the current log.
void GetCurrentSyntheticFieldTrials(
@@ -447,6 +468,9 @@ class MetricsService : public base::HistogramFlattener {
// Field trial groups that map to Chrome configuration states.
SyntheticTrialGroups synthetic_trial_groups_;
+ // List of observers of |synthetic_trial_groups_| changes.
+ ObserverList<SyntheticTrialObserver> synthetic_trial_observer_list_;
+
// Execution phase the browser is in.
static ExecutionPhase execution_phase_;
diff --git a/components/variations.gypi b/components/variations.gypi
index ee3a412..bf2cc37 100644
--- a/components/variations.gypi
+++ b/components/variations.gypi
@@ -71,6 +71,7 @@
'dependencies': [
'../base/base.gyp:base',
'components.gyp:google_core_browser',
+ "components.gyp:metrics",
'variations',
],
'sources': [
diff --git a/components/variations/net/BUILD.gn b/components/variations/net/BUILD.gn
index e35f5a84..34158fe 100644
--- a/components/variations/net/BUILD.gn
+++ b/components/variations/net/BUILD.gn
@@ -12,6 +12,7 @@ source_set("net") {
deps = [
"//base",
"//components/google/core/browser",
+ "//components/metrics",
"//components/variations/proto",
"//net",
]
diff --git a/components/variations/net/DEPS b/components/variations/net/DEPS
index f4a5acd..1abc71b 100644
--- a/components/variations/net/DEPS
+++ b/components/variations/net/DEPS
@@ -1,4 +1,5 @@
include_rules = [
"+components/google",
+ "+components/metrics",
"+net",
]
diff --git a/components/variations/net/variations_http_header_provider.cc b/components/variations/net/variations_http_header_provider.cc
index 1220fae..fa630cf 100644
--- a/components/variations/net/variations_http_header_provider.cc
+++ b/components/variations/net/variations_http_header_provider.cc
@@ -137,6 +137,20 @@ void VariationsHttpHeaderProvider::OnFieldTrialGroupFinalized(
UpdateVariationIDsHeaderValue();
}
+void VariationsHttpHeaderProvider::OnSyntheticTrialsChanged(
+ const std::vector<metrics::SyntheticTrialGroup>& groups) {
+ base::AutoLock scoped_lock(lock_);
+
+ synthetic_variation_ids_set_.clear();
+ for (const metrics::SyntheticTrialGroup& group : groups) {
+ const VariationID id =
+ GetGoogleVariationIDFromHashes(GOOGLE_WEB_PROPERTIES, group.id);
+ if (id != EMPTY_ID)
+ synthetic_variation_ids_set_.insert(id);
+ }
+ UpdateVariationIDsHeaderValue();
+}
+
void VariationsHttpHeaderProvider::InitVariationIDsCacheIfNeeded() {
base::AutoLock scoped_lock(lock_);
if (variation_ids_cache_initialized_)
@@ -186,7 +200,8 @@ void VariationsHttpHeaderProvider::UpdateVariationIDsHeaderValue() {
variation_ids_header_.clear();
if (variation_ids_set_.empty() && default_variation_ids_set_.empty() &&
- variation_trigger_ids_set_.empty() && default_trigger_id_set_.empty()) {
+ variation_trigger_ids_set_.empty() && default_trigger_id_set_.empty() &&
+ synthetic_variation_ids_set_.empty()) {
return;
}
@@ -203,26 +218,20 @@ void VariationsHttpHeaderProvider::UpdateVariationIDsHeaderValue() {
// Merge the two sets of experiment ids.
std::set<VariationID> all_variation_ids_set = default_variation_ids_set_;
- for (std::set<VariationID>::const_iterator it = variation_ids_set_.begin();
- it != variation_ids_set_.end(); ++it) {
- all_variation_ids_set.insert(*it);
- }
- ClientVariations proto;
- for (std::set<VariationID>::const_iterator it = all_variation_ids_set.begin();
- it != all_variation_ids_set.end(); ++it) {
- proto.add_variation_id(*it);
- }
+ for (VariationID id : variation_ids_set_)
+ all_variation_ids_set.insert(id);
+ for (VariationID id : synthetic_variation_ids_set_)
+ all_variation_ids_set.insert(id);
std::set<VariationID> all_trigger_ids_set = default_trigger_id_set_;
- for (std::set<VariationID>::const_iterator it =
- variation_trigger_ids_set_.begin();
- it != variation_trigger_ids_set_.end(); ++it) {
- all_trigger_ids_set.insert(*it);
- }
- for (std::set<VariationID>::const_iterator it = all_trigger_ids_set.begin();
- it != all_trigger_ids_set.end(); ++it) {
- proto.add_trigger_variation_id(*it);
- }
+ for (VariationID id : variation_trigger_ids_set_)
+ all_trigger_ids_set.insert(id);
+
+ ClientVariations proto;
+ for (VariationID id : all_variation_ids_set)
+ proto.add_variation_id(id);
+ for (VariationID id : all_trigger_ids_set)
+ proto.add_trigger_variation_id(id);
std::string serialized;
proto.SerializeToString(&serialized);
diff --git a/components/variations/net/variations_http_header_provider.h b/components/variations/net/variations_http_header_provider.h
index a0e3046..0a511cc 100644
--- a/components/variations/net/variations_http_header_provider.h
+++ b/components/variations/net/variations_http_header_provider.h
@@ -7,11 +7,13 @@
#include <set>
#include <string>
+#include <vector>
#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/metrics/field_trial.h"
#include "base/synchronization/lock.h"
+#include "components/metrics/metrics_service.h"
#include "components/variations/variations_associated_data.h"
namespace content {
@@ -31,7 +33,8 @@ namespace variations {
// A helper class for maintaining client experiments and metrics state
// transmitted in custom HTTP request headers.
// This class is a thread-safe singleton.
-class VariationsHttpHeaderProvider : base::FieldTrialList::Observer {
+class VariationsHttpHeaderProvider : public base::FieldTrialList::Observer,
+ public metrics::SyntheticTrialObserver {
public:
static VariationsHttpHeaderProvider* GetInstance();
@@ -66,12 +69,16 @@ class VariationsHttpHeaderProvider : base::FieldTrialList::Observer {
VariationsHttpHeaderProvider();
~VariationsHttpHeaderProvider() override;
- // base::FieldTrialList::Observer implementation.
+ // base::FieldTrialList::Observer:
// This will add the variation ID associated with |trial_name| and
// |group_name| to the variation ID cache.
void OnFieldTrialGroupFinalized(const std::string& trial_name,
const std::string& group_name) override;
+ // metrics::SyntheticTrialObserver:
+ void OnSyntheticTrialsChanged(
+ const std::vector<metrics::SyntheticTrialGroup>& groups) override;
+
// Prepares the variation IDs cache with initial values if not already done.
// This method also registers the caller with the FieldTrialList to receive
// new variation IDs.
@@ -102,6 +109,9 @@ class VariationsHttpHeaderProvider : base::FieldTrialList::Observer {
std::set<VariationID> default_variation_ids_set_;
std::set<VariationID> default_trigger_id_set_;
+ // Variations ids from synthetic field trials.
+ std::set<VariationID> synthetic_variation_ids_set_;
+
std::string variation_ids_header_;
DISALLOW_COPY_AND_ASSIGN(VariationsHttpHeaderProvider);
diff --git a/components/variations/variations_associated_data.cc b/components/variations/variations_associated_data.cc
index 6ef2343..857ded5 100644
--- a/components/variations/variations_associated_data.cc
+++ b/components/variations/variations_associated_data.cc
@@ -184,17 +184,29 @@ void AssociateGoogleVariationIDForce(IDCollectionKey key,
const std::string& trial_name,
const std::string& group_name,
VariationID id) {
- GroupMapAccessor::GetInstance()->AssociateID(
- key, MakeActiveGroupId(trial_name, group_name), id, true);
+ AssociateGoogleVariationIDForceHashes(
+ key, MakeActiveGroupId(trial_name, group_name), id);
+}
+
+void AssociateGoogleVariationIDForceHashes(IDCollectionKey key,
+ const ActiveGroupId& active_group,
+ VariationID id) {
+ GroupMapAccessor::GetInstance()->AssociateID(key, active_group, id, true);
}
VariationID GetGoogleVariationID(IDCollectionKey key,
const std::string& trial_name,
const std::string& group_name) {
- return GroupMapAccessor::GetInstance()->GetID(
+ return GetGoogleVariationIDFromHashes(
key, MakeActiveGroupId(trial_name, group_name));
}
+VariationID GetGoogleVariationIDFromHashes(
+ IDCollectionKey key,
+ const ActiveGroupId& active_group) {
+ return GroupMapAccessor::GetInstance()->GetID(key, active_group);
+}
+
bool AssociateVariationParams(
const std::string& trial_name,
const std::string& group_name,
diff --git a/components/variations/variations_associated_data.h b/components/variations/variations_associated_data.h
index 8bacae1..3fe70f8 100644
--- a/components/variations/variations_associated_data.h
+++ b/components/variations/variations_associated_data.h
@@ -82,6 +82,11 @@ void AssociateGoogleVariationIDForce(IDCollectionKey key,
const std::string& group_name,
VariationID id);
+// As above, but takes an ActiveGroupId hash pair, rather than the string names.
+void AssociateGoogleVariationIDForceHashes(IDCollectionKey key,
+ const ActiveGroupId& active_group,
+ VariationID id);
+
// Retrieve the variations::VariationID associated with a FieldTrial group for
// collection |key|. The group is denoted by |trial_name| and |group_name|.
// This will return variations::kEmptyID if there is currently no associated ID
@@ -92,6 +97,11 @@ VariationID GetGoogleVariationID(IDCollectionKey key,
const std::string& trial_name,
const std::string& group_name);
+// Same as GetGoogleVariationID(), but takes in a hashed |active_group| rather
+// than the string trial and group name.
+VariationID GetGoogleVariationIDFromHashes(IDCollectionKey key,
+ const ActiveGroupId& active_group);
+
// Associates the specified set of key-value |params| with the variation
// specified by |trial_name| and |group_name|. Fails and returns false if the
// specified variation already has params associated with it or the field trial