summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/android/contextualsearch/contextual_search_delegate.cc7
-rw-r--r--chrome/browser/chrome_browser_main.cc2
-rw-r--r--chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc18
-rw-r--r--chrome/browser/safe_browsing/srt_fetcher_win.cc8
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/chrome_browser_chromeos.gypi2
-rw-r--r--components/autofill.gypi2
-rw-r--r--components/autofill/core/browser/autofill_download_manager.cc5
-rw-r--r--components/components_tests.gyp5
-rw-r--r--components/feedback.gypi2
-rw-r--r--components/feedback/feedback_uploader_chrome.cc4
-rw-r--r--components/feedback/feedback_uploader_chrome_unittest.cc4
-rw-r--r--components/metrics/metrics_service.cc20
-rw-r--r--components/metrics/metrics_service.h67
-rw-r--r--components/metrics/metrics_service_accessor.cc2
-rw-r--r--components/metrics/metrics_service_unittest.cc12
-rw-r--r--components/omnibox.gypi2
-rw-r--r--components/omnibox/browser/search_provider.cc4
-rw-r--r--components/omnibox/browser/zero_suggest_provider.cc8
-rw-r--r--components/suggestions.gypi2
-rw-r--r--components/suggestions/suggestions_service.cc6
-rw-r--r--components/variations.gypi10
-rw-r--r--components/variations/BUILD.gn7
-rw-r--r--components/variations/net/BUILD.gn4
-rw-r--r--components/variations/net/variations_http_header_provider_unittest.cc238
-rw-r--r--components/variations/net/variations_http_headers.cc98
-rw-r--r--components/variations/net/variations_http_headers.h41
-rw-r--r--components/variations/net/variations_http_headers_unittest.cc111
-rw-r--r--components/variations/synthetic_trials.cc16
-rw-r--r--components/variations/synthetic_trials.h41
-rw-r--r--components/variations/variations_http_header_provider.cc (renamed from components/variations/net/variations_http_header_provider.cc)115
-rw-r--r--components/variations/variations_http_header_provider.h (renamed from components/variations/net/variations_http_header_provider.h)45
-rw-r--r--components/variations/variations_http_header_provider_unittest.cc126
33 files changed, 549 insertions, 487 deletions
diff --git a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
index b4e206e..ded49f7 100644
--- a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
+++ b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
@@ -22,7 +22,7 @@
#include "chrome/common/pref_names.h"
#include "components/browser_sync/browser/profile_sync_service.h"
#include "components/search_engines/template_url_service.h"
-#include "components/variations/net/variations_http_header_provider.h"
+#include "components/variations/net/variations_http_headers.h"
#include "components/variations/variations_associated_data.h"
#include "content/public/browser/android/content_view_core.h"
#include "content/public/browser/web_contents.h"
@@ -128,11 +128,10 @@ void ContextualSearchDelegate::ContinueSearchTermResolutionRequest() {
// Add Chrome experiment state to the request headers.
net::HttpRequestHeaders headers;
- variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders(
+ variations::AppendVariationHeaders(
search_term_fetcher_->GetOriginalURL(),
false, // Impossible to be incognito at this point.
- false,
- &headers);
+ false, &headers);
search_term_fetcher_->SetExtraRequestHeaders(headers.ToString());
SetDiscourseContextAndAddToHeader(*context_);
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 3f042a7..286cf34 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -123,10 +123,10 @@
#include "components/translate/content/browser/browser_cld_utils.h"
#include "components/translate/content/common/cld_data_source.h"
#include "components/translate/core/browser/translate_download_manager.h"
-#include "components/variations/net/variations_http_header_provider.h"
#include "components/variations/pref_names.h"
#include "components/variations/service/variations_service.h"
#include "components/variations/variations_associated_data.h"
+#include "components/variations/variations_http_header_provider.h"
#include "components/variations/variations_switches.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
index f552005..a8e6fa8 100644
--- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
+++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
@@ -37,7 +37,7 @@
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
#include "components/google/core/browser/google_util.h"
-#include "components/variations/net/variations_http_header_provider.h"
+#include "components/variations/net/variations_http_headers.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/plugin_service.h"
@@ -285,11 +285,9 @@ ChromeResourceDispatcherHostDelegate::ChromeResourceDispatcherHostDelegate()
#endif
{
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
+ BrowserThread::IO, FROM_HERE,
base::Bind(content::ServiceWorkerContext::AddExcludedHeadersForFetchEvent,
- variations::VariationsHttpHeaderProvider::GetInstance()
- ->GetVariationHeaderNames()));
+ variations::GetVariationHeaderNames()));
}
ChromeResourceDispatcherHostDelegate::~ChromeResourceDispatcherHostDelegate() {
@@ -371,12 +369,10 @@ void ChromeResourceDispatcherHostDelegate::RequestBeginning(
net::HttpRequestHeaders headers;
headers.CopyFrom(request->extra_request_headers());
bool is_off_the_record = io_data->IsOffTheRecord();
- variations::VariationsHttpHeaderProvider::GetInstance()->
- AppendHeaders(request->url(),
- is_off_the_record,
- !is_off_the_record &&
- io_data->GetMetricsEnabledStateOnIOThread(),
- &headers);
+ variations::AppendVariationHeaders(
+ request->url(), is_off_the_record,
+ !is_off_the_record && io_data->GetMetricsEnabledStateOnIOThread(),
+ &headers);
request->SetExtraRequestHeaders(headers);
}
diff --git a/chrome/browser/safe_browsing/srt_fetcher_win.cc b/chrome/browser/safe_browsing/srt_fetcher_win.cc
index 9e616be..1640804 100644
--- a/chrome/browser/safe_browsing/srt_fetcher_win.cc
+++ b/chrome/browser/safe_browsing/srt_fetcher_win.cc
@@ -12,6 +12,7 @@
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/metrics/field_trial.h"
+#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
#include "base/prefs/pref_service.h"
#include "base/process/launch.h"
@@ -35,7 +36,7 @@
#include "chrome/browser/ui/global_error/global_error_service_factory.h"
#include "components/component_updater/pref_names.h"
#include "components/rappor/rappor_service.h"
-#include "components/variations/net/variations_http_header_provider.h"
+#include "components/variations/net/variations_http_headers.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/load_flags.h"
#include "net/http/http_status_code.h"
@@ -230,9 +231,8 @@ class SRTFetcher : public net::URLFetcherDelegate {
ProfileIOData* io_data = ProfileIOData::FromResourceContext(
profile_->GetResourceContext());
net::HttpRequestHeaders headers;
- variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders(
- url_fetcher_->GetOriginalURL(),
- io_data->IsOffTheRecord(),
+ variations::AppendVariationHeaders(
+ url_fetcher_->GetOriginalURL(), io_data->IsOffTheRecord(),
ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled(),
&headers);
url_fetcher_->SetExtraRequestHeaders(headers.ToString());
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index fb8e42a..7de8592 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -3194,7 +3194,7 @@
# transitively via the common target because the proto sources need to
# be generated before code in this target can start building.
'../components/components.gyp:variations',
- '../components/components.gyp:variations_http_provider',
+ '../components/components.gyp:variations_net',
'../components/components.gyp:variations_service',
'../components/components.gyp:webdata_common',
'../components/components.gyp:webdata_services',
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi
index ff74e43..d75c5b8 100644
--- a/chrome/chrome_browser_chromeos.gypi
+++ b/chrome/chrome_browser_chromeos.gypi
@@ -1132,7 +1132,7 @@
# transitively via the common target because the proto sources need to
# be generated before code in this target can start building.
'../components/components.gyp:variations',
- '../components/components.gyp:variations_http_provider',
+ '../components/components.gyp:variations_net',
'../components/components.gyp:wallpaper',
'../components/components.gyp:wifi_sync',
'../components/components_strings.gyp:components_strings',
diff --git a/components/autofill.gypi b/components/autofill.gypi
index a15cd11..5d07ed2 100644
--- a/components/autofill.gypi
+++ b/components/autofill.gypi
@@ -96,7 +96,7 @@
'signin_core_browser',
'signin_core_common',
'sync_driver',
- 'variations_http_provider',
+ 'variations_net',
'webdata_common',
],
'sources': [
diff --git a/components/autofill/core/browser/autofill_download_manager.cc b/components/autofill/core/browser/autofill_download_manager.cc
index 59578fe..0b92381 100644
--- a/components/autofill/core/browser/autofill_download_manager.cc
+++ b/components/autofill/core/browser/autofill_download_manager.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/location.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/rand_util.h"
@@ -20,7 +21,7 @@
#include "components/autofill/core/common/autofill_pref_names.h"
#include "components/compression/compression_utils.h"
#include "components/data_use_measurement/core/data_use_user_data.h"
-#include "components/variations/net/variations_http_header_provider.h"
+#include "components/variations/net/variations_http_headers.h"
#include "net/base/load_flags.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
@@ -205,7 +206,7 @@ bool AutofillDownloadManager::StartRequest(
// Add Chrome experiment state and GZIP encoding to the request headers.
net::HttpRequestHeaders headers;
headers.SetHeaderIfMissing("content-encoding", "gzip");
- variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders(
+ variations::AppendVariationHeaders(
fetcher->GetOriginalURL(), driver_->IsOffTheRecord(), false, &headers);
fetcher->SetExtraRequestHeaders(headers.ToString());
fetcher->Start();
diff --git a/components/components_tests.gyp b/components/components_tests.gyp
index 5f16283..df387a3 100644
--- a/components/components_tests.gyp
+++ b/components/components_tests.gyp
@@ -798,11 +798,12 @@
'variations/entropy_provider_unittest.cc',
'variations/experiment_labels_unittest.cc',
'variations/metrics_util_unittest.cc',
- 'variations/net/variations_http_header_provider_unittest.cc',
+ 'variations/net/variations_http_headers_unittest.cc',
'variations/service/ui_string_overrider_unittest.cc',
'variations/service/variations_service_unittest.cc',
'variations/study_filtering_unittest.cc',
'variations/variations_associated_data_unittest.cc',
+ 'variations/variations_http_header_provider_unittest.cc',
'variations/variations_request_scheduler_mobile_unittest.cc',
'variations/variations_request_scheduler_unittest.cc',
'variations/variations_seed_processor_unittest.cc',
@@ -1090,7 +1091,7 @@
'components.gyp:user_prefs_tracked',
'components.gyp:user_prefs_tracked_test_support',
'components.gyp:variations',
- 'components.gyp:variations_http_provider',
+ 'components.gyp:variations_net',
'components.gyp:variations_service',
'components.gyp:version_info',
'components.gyp:web_resource',
diff --git a/components/feedback.gypi b/components/feedback.gypi
index d51592c..4c25308 100644
--- a/components/feedback.gypi
+++ b/components/feedback.gypi
@@ -14,7 +14,7 @@
'../third_party/zlib/google/zip.gyp:zip',
'keyed_service_core',
'feedback_proto',
- 'components.gyp:variations_http_provider',
+ 'components.gyp:variations_net',
],
'include_dirs': [
'..',
diff --git a/components/feedback/feedback_uploader_chrome.cc b/components/feedback/feedback_uploader_chrome.cc
index aea651f4..fa9951b 100644
--- a/components/feedback/feedback_uploader_chrome.cc
+++ b/components/feedback/feedback_uploader_chrome.cc
@@ -14,7 +14,7 @@
#include "components/feedback/feedback_report.h"
#include "components/feedback/feedback_switches.h"
#include "components/feedback/feedback_uploader_delegate.h"
-#include "components/variations/net/variations_http_header_provider.h"
+#include "components/variations/net/variations_http_headers.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/load_flags.h"
@@ -57,7 +57,7 @@ void FeedbackUploaderChrome::DispatchReport(const std::string& data) {
// Tell feedback server about the variation state of this install.
net::HttpRequestHeaders headers;
- variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders(
+ variations::AppendVariationHeaders(
fetcher->GetOriginalURL(), context_->IsOffTheRecord(), false, &headers);
fetcher->SetExtraRequestHeaders(headers.ToString());
diff --git a/components/feedback/feedback_uploader_chrome_unittest.cc b/components/feedback/feedback_uploader_chrome_unittest.cc
index 810c040..342e896 100644
--- a/components/feedback/feedback_uploader_chrome_unittest.cc
+++ b/components/feedback/feedback_uploader_chrome_unittest.cc
@@ -4,10 +4,12 @@
#include "components/feedback/feedback_uploader_chrome.h"
+#include <string>
+
#include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h"
-#include "components/variations/net/variations_http_header_provider.h"
#include "components/variations/variations_associated_data.h"
+#include "components/variations/variations_http_header_provider.h"
#include "content/public/test/test_browser_context.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_fetcher_delegate.h"
diff --git a/components/metrics/metrics_service.cc b/components/metrics/metrics_service.cc
index 55aa9f1..f84deaf 100644
--- a/components/metrics/metrics_service.cc
+++ b/components/metrics/metrics_service.cc
@@ -242,15 +242,6 @@ bool ShouldUploadLog() {
} // namespace
-
-SyntheticTrialGroup::SyntheticTrialGroup(uint32 trial, uint32 group) {
- id.name = trial;
- id.group = group;
-}
-
-SyntheticTrialGroup::~SyntheticTrialGroup() {
-}
-
// static
MetricsService::ShutdownCleanliness MetricsService::clean_shutdown_status_ =
MetricsService::CLEANLY_SHUTDOWN;
@@ -1025,19 +1016,19 @@ bool MetricsService::UmaMetricsProperlyShutdown() {
}
void MetricsService::AddSyntheticTrialObserver(
- SyntheticTrialObserver* observer) {
+ variations::SyntheticTrialObserver* observer) {
synthetic_trial_observer_list_.AddObserver(observer);
if (!synthetic_trial_groups_.empty())
observer->OnSyntheticTrialsChanged(synthetic_trial_groups_);
}
void MetricsService::RemoveSyntheticTrialObserver(
- SyntheticTrialObserver* observer) {
+ variations::SyntheticTrialObserver* observer) {
synthetic_trial_observer_list_.RemoveObserver(observer);
}
void MetricsService::RegisterSyntheticFieldTrial(
- const SyntheticTrialGroup& trial) {
+ const variations::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) {
@@ -1049,7 +1040,7 @@ void MetricsService::RegisterSyntheticFieldTrial(
}
}
- SyntheticTrialGroup trial_group = trial;
+ variations::SyntheticTrialGroup trial_group = trial;
trial_group.start_time = base::TimeTicks::Now();
synthetic_trial_groups_.push_back(trial_group);
NotifySyntheticTrialObservers();
@@ -1072,7 +1063,8 @@ void MetricsService::CheckForClonedInstall(
}
void MetricsService::NotifySyntheticTrialObservers() {
- FOR_EACH_OBSERVER(SyntheticTrialObserver, synthetic_trial_observer_list_,
+ FOR_EACH_OBSERVER(variations::SyntheticTrialObserver,
+ synthetic_trial_observer_list_,
OnSyntheticTrialsChanged(synthetic_trial_groups_));
}
diff --git a/components/metrics/metrics_service.h b/components/metrics/metrics_service.h
index 2345083..0939c13 100644
--- a/components/metrics/metrics_service.h
+++ b/components/metrics/metrics_service.h
@@ -28,7 +28,7 @@
#include "components/metrics/metrics_log_manager.h"
#include "components/metrics/metrics_provider.h"
#include "components/metrics/net/network_metrics_provider.h"
-#include "components/variations/active_field_trials.h"
+#include "components/variations/synthetic_trials.h"
class PrefService;
class PrefRegistrySimple;
@@ -55,39 +55,6 @@ class MetricsServiceAccessor;
class MetricsServiceClient;
class MetricsStateManager;
-// A Field Trial and its selected group, which represent a particular
-// Chrome configuration state. For example, the trial name could map to
-// a preference name, and the group name could map to a preference value.
-struct SyntheticTrialGroup {
- public:
- ~SyntheticTrialGroup();
-
- variations::ActiveGroupId id;
- base::TimeTicks start_time;
-
- private:
- // Synthetic field trial users:
- friend class MetricsServiceAccessor;
- friend class MetricsService;
- FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, RegisterSyntheticTrial);
-
- // This constructor is private specifically so as to control which code is
- // able to access it. New code that wishes to use it should be added as a
- // friend class.
- 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:
@@ -216,26 +183,17 @@ class MetricsService : public base::HistogramFlattener {
// This value should be true when process has completed shutdown.
static bool UmaMetricsProperlyShutdown();
- // Registers a field trial name and group to be used to annotate a UMA report
- // with a particular Chrome configuration state. A UMA report will be
- // annotated with this trial group if and only if all events in the report
- // were created after the trial is registered. Only one group name may be
- // registered at a time for a given trial_name. Only the last group name that
- // is registered for a given trial name will be recorded. The values passed
- // in must not correspond to any real field trial in the code.
- // To use this method, SyntheticTrialGroup should friend your class.
- void RegisterSyntheticFieldTrial(const SyntheticTrialGroup& trial_group);
-
// Public accessor that returns the list of synthetic field trials. It must
// only be used for testing.
void GetCurrentSyntheticFieldTrialsForTesting(
std::vector<variations::ActiveGroupId>* synthetic_trials);
// Adds an observer to be notified when the synthetic trials list changes.
- void AddSyntheticTrialObserver(SyntheticTrialObserver* observer);
+ void AddSyntheticTrialObserver(variations::SyntheticTrialObserver* observer);
// Removes an existing observer of synthetic trials list changes.
- void RemoveSyntheticTrialObserver(SyntheticTrialObserver* observer);
+ void RemoveSyntheticTrialObserver(
+ variations::SyntheticTrialObserver* observer);
// Register the specified |provider| to provide additional metrics into the
// UMA log. Should be called during MetricsService initialization only.
@@ -258,6 +216,8 @@ class MetricsService : public base::HistogramFlattener {
MetricsLogManager* log_manager() { return &log_manager_; }
private:
+ friend class MetricsServiceAccessor;
+
// The MetricsService has a lifecycle that is stored as a state.
// See metrics_service.cc for description of this lifecycle.
enum State {
@@ -281,7 +241,17 @@ class MetricsService : public base::HistogramFlattener {
UNSET
};
- typedef std::vector<SyntheticTrialGroup> SyntheticTrialGroups;
+ typedef std::vector<variations::SyntheticTrialGroup> SyntheticTrialGroups;
+
+ // Registers a field trial name and group to be used to annotate a UMA report
+ // with a particular Chrome configuration state. A UMA report will be
+ // annotated with this trial group if and only if all events in the report
+ // were created after the trial is registered. Only one group name may be
+ // registered at a time for a given trial_name. Only the last group name that
+ // is registered for a given trial name will be recorded. The values passed
+ // in must not correspond to any real field trial in the code.
+ void RegisterSyntheticFieldTrial(
+ const variations::SyntheticTrialGroup& trial_group);
// Calls into the client to initialize some system profile metrics.
void StartInitTask();
@@ -489,7 +459,8 @@ class MetricsService : public base::HistogramFlattener {
SyntheticTrialGroups synthetic_trial_groups_;
// List of observers of |synthetic_trial_groups_| changes.
- base::ObserverList<SyntheticTrialObserver> synthetic_trial_observer_list_;
+ base::ObserverList<variations::SyntheticTrialObserver>
+ synthetic_trial_observer_list_;
// Execution phase the browser is in.
static ExecutionPhase execution_phase_;
diff --git a/components/metrics/metrics_service_accessor.cc b/components/metrics/metrics_service_accessor.cc
index 864dbe5..ce301c9 100644
--- a/components/metrics/metrics_service_accessor.cc
+++ b/components/metrics/metrics_service_accessor.cc
@@ -62,7 +62,7 @@ bool MetricsServiceAccessor::RegisterSyntheticFieldTrialWithNameAndGroupHash(
if (!metrics_service)
return false;
- SyntheticTrialGroup trial_group(trial_name_hash, group_name_hash);
+ variations::SyntheticTrialGroup trial_group(trial_name_hash, group_name_hash);
metrics_service->RegisterSyntheticFieldTrial(trial_group);
return true;
}
diff --git a/components/metrics/metrics_service_unittest.cc b/components/metrics/metrics_service_unittest.cc
index b306c9b..e3de5ae 100644
--- a/components/metrics/metrics_service_unittest.cc
+++ b/components/metrics/metrics_service_unittest.cc
@@ -315,10 +315,12 @@ TEST_F(MetricsServiceTest, RegisterSyntheticTrial) {
MetricsService service(GetMetricsStateManager(), &client, GetLocalState());
// Add two synthetic trials and confirm that they show up in the list.
- SyntheticTrialGroup trial1(HashName("TestTrial1"), HashName("Group1"));
+ variations::SyntheticTrialGroup trial1(HashName("TestTrial1"),
+ HashName("Group1"));
service.RegisterSyntheticFieldTrial(trial1);
- SyntheticTrialGroup trial2(HashName("TestTrial2"), HashName("Group2"));
+ variations::SyntheticTrialGroup trial2(HashName("TestTrial2"),
+ HashName("Group2"));
service.RegisterSyntheticFieldTrial(trial2);
// Ensure that time has advanced by at least a tick before proceeding.
WaitUntilTimeChanges(base::TimeTicks::Now());
@@ -345,14 +347,16 @@ TEST_F(MetricsServiceTest, RegisterSyntheticTrial) {
WaitUntilTimeChanges(begin_log_time);
// Change the group for the first trial after the log started.
- SyntheticTrialGroup trial3(HashName("TestTrial1"), HashName("Group2"));
+ variations::SyntheticTrialGroup trial3(HashName("TestTrial1"),
+ HashName("Group2"));
service.RegisterSyntheticFieldTrial(trial3);
service.GetSyntheticFieldTrialsOlderThan(begin_log_time, &synthetic_trials);
EXPECT_EQ(1U, synthetic_trials.size());
EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2"));
// Add a new trial after the log started and confirm that it doesn't show up.
- SyntheticTrialGroup trial4(HashName("TestTrial3"), HashName("Group3"));
+ variations::SyntheticTrialGroup trial4(HashName("TestTrial3"),
+ HashName("Group3"));
service.RegisterSyntheticFieldTrial(trial4);
service.GetSyntheticFieldTrialsOlderThan(begin_log_time, &synthetic_trials);
EXPECT_EQ(1U, synthetic_trials.size());
diff --git a/components/omnibox.gypi b/components/omnibox.gypi
index 8b2841d..dcb0536 100644
--- a/components/omnibox.gypi
+++ b/components/omnibox.gypi
@@ -37,7 +37,7 @@
'search_engines',
'toolbar',
'url_formatter/url_formatter.gyp:url_formatter',
- 'variations_http_provider',
+ 'variations_net',
],
'export_dependent_settings': [
'component_metrics_proto',
diff --git a/components/omnibox/browser/search_provider.cc b/components/omnibox/browser/search_provider.cc
index c3c9a25..b26910c 100644
--- a/components/omnibox/browser/search_provider.cc
+++ b/components/omnibox/browser/search_provider.cc
@@ -33,7 +33,7 @@
#include "components/search_engines/template_url_prepopulate_data.h"
#include "components/search_engines/template_url_service.h"
#include "components/url_formatter/url_formatter.h"
-#include "components/variations/net/variations_http_header_provider.h"
+#include "components/variations/net/variations_http_headers.h"
#include "grit/components_strings.h"
#include "net/base/escape.h"
#include "net/base/load_flags.h"
@@ -891,7 +891,7 @@ scoped_ptr<net::URLFetcher> SearchProvider::CreateSuggestFetcher(
fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES);
// Add Chrome experiment state to the request headers.
net::HttpRequestHeaders headers;
- variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders(
+ variations::AppendVariationHeaders(
fetcher->GetOriginalURL(), client()->IsOffTheRecord(), false, &headers);
fetcher->SetExtraRequestHeaders(headers.ToString());
fetcher->Start();
diff --git a/components/omnibox/browser/zero_suggest_provider.cc b/components/omnibox/browser/zero_suggest_provider.cc
index 9b9dcfc..a12a1b4 100644
--- a/components/omnibox/browser/zero_suggest_provider.cc
+++ b/components/omnibox/browser/zero_suggest_provider.cc
@@ -30,7 +30,7 @@
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/search_engines/template_url_service.h"
#include "components/url_formatter/url_formatter.h"
-#include "components/variations/net/variations_http_header_provider.h"
+#include "components/variations/net/variations_http_headers.h"
#include "net/base/escape.h"
#include "net/base/load_flags.h"
#include "net/http/http_request_headers.h"
@@ -326,9 +326,9 @@ void ZeroSuggestProvider::Run(const GURL& suggest_url) {
fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES);
// Add Chrome experiment state to the request headers.
net::HttpRequestHeaders headers;
- variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders(
- fetcher_->GetOriginalURL(), client()->IsOffTheRecord(), false,
- &headers);
+ variations::AppendVariationHeaders(fetcher_->GetOriginalURL(),
+ client()->IsOffTheRecord(), false,
+ &headers);
fetcher_->SetExtraRequestHeaders(headers.ToString());
fetcher_->Start();
LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_SENT);
diff --git a/components/suggestions.gypi b/components/suggestions.gypi
index 7be7e72..efffdef 100644
--- a/components/suggestions.gypi
+++ b/components/suggestions.gypi
@@ -20,7 +20,7 @@
'components.gyp:keyed_service_core',
'components.gyp:pref_registry',
'components.gyp:variations',
- 'components.gyp:variations_http_provider',
+ 'components.gyp:variations_net',
],
'sources': [
'suggestions/blacklist_store.cc',
diff --git a/components/suggestions/suggestions_service.cc b/components/suggestions/suggestions_service.cc
index d85194d..4382fde 100644
--- a/components/suggestions/suggestions_service.cc
+++ b/components/suggestions/suggestions_service.cc
@@ -20,7 +20,7 @@
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/suggestions/blacklist_store.h"
#include "components/suggestions/suggestions_store.h"
-#include "components/variations/net/variations_http_header_provider.h"
+#include "components/variations/net/variations_http_headers.h"
#include "net/base/escape.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
@@ -272,8 +272,8 @@ scoped_ptr<net::URLFetcher> SuggestionsService::CreateSuggestionsRequest(
request->SetRequestContext(url_request_context_);
// Add Chrome experiment state to the request headers.
net::HttpRequestHeaders headers;
- variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders(
- request->GetOriginalURL(), false, false, &headers);
+ variations::AppendVariationHeaders(request->GetOriginalURL(), false, false,
+ &headers);
request->SetExtraRequestHeaders(headers.ToString());
return request;
}
diff --git a/components/variations.gypi b/components/variations.gypi
index 9649110..157f68c 100644
--- a/components/variations.gypi
+++ b/components/variations.gypi
@@ -50,10 +50,14 @@
'variations/proto/variations_seed.proto',
'variations/study_filtering.cc',
'variations/study_filtering.h',
+ "variations/synthetic_trials.cc",
+ "variations/synthetic_trials.h",
'variations/variations_associated_data.cc',
'variations/variations_associated_data.h',
'variations/variations_experiment_util.cc',
'variations/variations_experiment_util.h',
+ 'variations/variations_http_header_provider.cc',
+ 'variations/variations_http_header_provider.h',
'variations/variations_request_scheduler.cc',
'variations/variations_request_scheduler.h',
'variations/variations_request_scheduler_mobile.cc',
@@ -119,7 +123,7 @@
},
{
# GN version: //components/variations/net:net
- 'target_name': 'variations_http_provider',
+ 'target_name': 'variations_net',
'type': 'static_library',
'include_dirs': [
'..',
@@ -136,8 +140,8 @@
'components.gyp:metrics',
],
'sources': [
- 'variations/net/variations_http_header_provider.cc',
- 'variations/net/variations_http_header_provider.h',
+ 'variations/net/variations_http_headers.cc',
+ 'variations/net/variations_http_headers.h',
],
},
],
diff --git a/components/variations/BUILD.gn b/components/variations/BUILD.gn
index a65148a..c490cab 100644
--- a/components/variations/BUILD.gn
+++ b/components/variations/BUILD.gn
@@ -34,10 +34,14 @@ source_set("variations") {
"proto/variations_seed.proto",
"study_filtering.cc",
"study_filtering.h",
+ "synthetic_trials.cc",
+ "synthetic_trials.h",
"variations_associated_data.cc",
"variations_associated_data.h",
"variations_experiment_util.cc",
"variations_experiment_util.h",
+ "variations_http_header_provider.cc",
+ "variations_http_header_provider.h",
"variations_request_scheduler.cc",
"variations_request_scheduler.h",
"variations_seed_processor.cc",
@@ -96,9 +100,10 @@ source_set("unit_tests") {
"entropy_provider_unittest.cc",
"experiment_labels_unittest.cc",
"metrics_util_unittest.cc",
- "net/variations_http_header_provider_unittest.cc",
+ "net/variations_http_headers_unittest.cc",
"study_filtering_unittest.cc",
"variations_associated_data_unittest.cc",
+ "variations_http_header_provider_unittest.cc",
"variations_request_scheduler_unittest.cc",
"variations_seed_processor_unittest.cc",
"variations_seed_simulator_unittest.cc",
diff --git a/components/variations/net/BUILD.gn b/components/variations/net/BUILD.gn
index 0511046..c037d46 100644
--- a/components/variations/net/BUILD.gn
+++ b/components/variations/net/BUILD.gn
@@ -4,8 +4,8 @@
source_set("net") {
sources = [
- "variations_http_header_provider.cc",
- "variations_http_header_provider.h",
+ "variations_http_headers.cc",
+ "variations_http_headers.h",
]
public_deps = [
diff --git a/components/variations/net/variations_http_header_provider_unittest.cc b/components/variations/net/variations_http_header_provider_unittest.cc
deleted file mode 100644
index 2cb5c81..0000000
--- a/components/variations/net/variations_http_header_provider_unittest.cc
+++ /dev/null
@@ -1,238 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/variations/net/variations_http_header_provider.h"
-
-#include <string>
-
-#include "base/base64.h"
-#include "base/message_loop/message_loop.h"
-#include "base/metrics/field_trial.h"
-#include "base/run_loop.h"
-#include "components/variations/entropy_provider.h"
-#include "components/variations/proto/client_variations.pb.h"
-#include "components/variations/variations_associated_data.h"
-#include "net/http/http_request_headers.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace variations {
-
-namespace {
-
-// Decodes the variations header and extracts the variation ids.
-bool ExtractVariationIds(const std::string& variations,
- std::set<VariationID>* variation_ids,
- std::set<VariationID>* trigger_ids) {
- std::string serialized_proto;
- if (!base::Base64Decode(variations, &serialized_proto))
- return false;
- ClientVariations proto;
- if (!proto.ParseFromString(serialized_proto)) return false;
- for (int i = 0; i < proto.variation_id_size(); ++i)
- variation_ids->insert(proto.variation_id(i));
- for (int i = 0; i < proto.trigger_variation_id_size(); ++i)
- trigger_ids->insert(proto.trigger_variation_id(i));
- return true;
-}
-
-scoped_refptr<base::FieldTrial> CreateTrialAndAssociateId(
- const std::string& trial_name,
- const std::string& default_group_name,
- IDCollectionKey key,
- VariationID id) {
- scoped_refptr<base::FieldTrial> trial(
- base::FieldTrialList::CreateFieldTrial(trial_name, default_group_name));
-
- AssociateGoogleVariationID(key, trial->trial_name(), trial->group_name(), id);
-
- return trial;
-}
-
-} // namespace
-
-class VariationsHttpHeaderProviderTest : public ::testing::Test {
- public:
- VariationsHttpHeaderProviderTest() {}
-
- ~VariationsHttpHeaderProviderTest() override {}
-
- void TearDown() override { testing::ClearAllVariationIDs(); }
-};
-
-TEST_F(VariationsHttpHeaderProviderTest, ShouldAppendHeaders) {
- struct {
- const char* url;
- bool should_append_headers;
- } cases[] = {
- {"http://google.com", true},
- {"http://www.google.com", true},
- {"http://m.google.com", true},
- {"http://google.ca", true},
- {"https://google.ca", true},
- {"http://google.co.uk", true},
- {"http://google.co.uk:8080/", true},
- {"http://www.google.co.uk:8080/", true},
- {"http://google", false},
-
- {"http://youtube.com", true},
- {"http://www.youtube.com", true},
- {"http://www.youtube.ca", true},
- {"http://www.youtube.co.uk:8080/", true},
- {"https://www.youtube.com", true},
- {"http://youtube", false},
-
- {"http://www.yahoo.com", false},
-
- {"http://ad.doubleclick.net", true},
- {"https://a.b.c.doubleclick.net", true},
- {"https://a.b.c.doubleclick.net:8081", true},
- {"http://www.doubleclick.com", true},
- {"http://www.doubleclick.org", false},
- {"http://www.doubleclick.net.com", false},
- {"https://www.doubleclick.net.com", false},
-
- {"http://ad.googlesyndication.com", true},
- {"https://a.b.c.googlesyndication.com", true},
- {"https://a.b.c.googlesyndication.com:8080", true},
- {"http://www.doubleclick.edu", false},
- {"http://www.googlesyndication.com.edu", false},
- {"https://www.googlesyndication.com.com", false},
-
- {"http://www.googleadservices.com", true},
- {"http://www.googleadservices.com:8080", true},
- {"https://www.googleadservices.com", true},
- {"https://www.internal.googleadservices.com", true},
- {"https://www2.googleadservices.com", true},
- {"https://www.googleadservices.org", false},
- {"https://www.googleadservices.com.co.uk", false},
-
- {"http://WWW.ANDROID.COM", true},
- {"http://www.android.com", true},
- {"http://www.doubleclick.com", true},
- {"http://www.doubleclick.net", true},
- {"http://www.ggpht.com", true},
- {"http://www.googleadservices.com", true},
- {"http://www.googleapis.com", true},
- {"http://www.googlesyndication.com", true},
- {"http://www.googleusercontent.com", true},
- {"http://www.googlevideo.com", true},
- {"http://ssl.gstatic.com", true},
- {"http://www.gstatic.com", true},
- {"http://www.ytimg.com", true},
- {"http://wwwytimg.com", false},
- {"http://ytimg.com", false},
-
- {"http://www.android.org", false},
- {"http://www.doubleclick.org", false},
- {"http://www.doubleclick.net", true},
- {"http://www.ggpht.org", false},
- {"http://www.googleadservices.org", false},
- {"http://www.googleapis.org", false},
- {"http://www.googlesyndication.org", false},
- {"http://www.googleusercontent.org", false},
- {"http://www.googlevideo.org", false},
- {"http://ssl.gstatic.org", false},
- {"http://www.gstatic.org", false},
- {"http://www.ytimg.org", false},
-
- {"http://a.b.android.com", true},
- {"http://a.b.doubleclick.com", true},
- {"http://a.b.doubleclick.net", true},
- {"http://a.b.ggpht.com", true},
- {"http://a.b.googleadservices.com", true},
- {"http://a.b.googleapis.com", true},
- {"http://a.b.googlesyndication.com", true},
- {"http://a.b.googleusercontent.com", true},
- {"http://a.b.googlevideo.com", true},
- {"http://ssl.gstatic.com", true},
- {"http://a.b.gstatic.com", true},
- {"http://a.b.ytimg.com", true},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- const GURL url(cases[i].url);
- EXPECT_EQ(cases[i].should_append_headers,
- VariationsHttpHeaderProvider::ShouldAppendHeaders(url))
- << url;
- }
-}
-
-TEST_F(VariationsHttpHeaderProviderTest, SetDefaultVariationIds_Valid) {
- base::MessageLoop loop;
- VariationsHttpHeaderProvider provider;
- GURL url("http://www.google.com");
- net::HttpRequestHeaders headers;
- std::string variations;
-
- // Valid experiment ids.
- EXPECT_TRUE(provider.SetDefaultVariationIds("12,456,t789"));
- provider.InitVariationIDsCacheIfNeeded();
- provider.AppendHeaders(url, false, false, &headers);
- EXPECT_TRUE(headers.HasHeader("X-Client-Data"));
- headers.GetHeader("X-Client-Data", &variations);
- std::set<VariationID> variation_ids;
- std::set<VariationID> trigger_ids;
- ASSERT_TRUE(ExtractVariationIds(variations, &variation_ids, &trigger_ids));
- EXPECT_TRUE(variation_ids.find(12) != variation_ids.end());
- EXPECT_TRUE(variation_ids.find(456) != variation_ids.end());
- EXPECT_TRUE(trigger_ids.find(789) != trigger_ids.end());
- EXPECT_FALSE(variation_ids.find(789) != variation_ids.end());
-}
-
-TEST_F(VariationsHttpHeaderProviderTest, SetDefaultVariationIds_Invalid) {
- base::MessageLoop loop;
- VariationsHttpHeaderProvider provider;
- GURL url("http://www.google.com");
- net::HttpRequestHeaders headers;
-
- // Invalid experiment ids.
- EXPECT_FALSE(provider.SetDefaultVariationIds("abcd12,456"));
- provider.InitVariationIDsCacheIfNeeded();
- provider.AppendHeaders(url, false, false, &headers);
- EXPECT_FALSE(headers.HasHeader("X-Client-Data"));
-
- // Invalid trigger experiment id
- EXPECT_FALSE(provider.SetDefaultVariationIds("12,tabc456"));
- provider.InitVariationIDsCacheIfNeeded();
- provider.AppendHeaders(url, false, false, &headers);
- EXPECT_FALSE(headers.HasHeader("X-Client-Data"));
-}
-
-TEST_F(VariationsHttpHeaderProviderTest, OnFieldTrialGroupFinalized) {
- base::MessageLoop loop;
- base::FieldTrialList field_trial_list(
- new metrics::SHA1EntropyProvider("test"));
- VariationsHttpHeaderProvider provider;
- provider.InitVariationIDsCacheIfNeeded();
-
- const std::string default_name = "default";
- scoped_refptr<base::FieldTrial> trial_1(CreateTrialAndAssociateId(
- "t1", default_name, GOOGLE_WEB_PROPERTIES, 123));
-
- ASSERT_EQ(default_name, trial_1->group_name());
-
- scoped_refptr<base::FieldTrial> trial_2(CreateTrialAndAssociateId(
- "t2", default_name, GOOGLE_WEB_PROPERTIES_TRIGGER, 456));
-
- ASSERT_EQ(default_name, trial_2->group_name());
-
- // Run the message loop to make sure OnFieldTrialGroupFinalized is called for
- // the two field trials.
- base::RunLoop().RunUntilIdle();
-
- GURL url("http://www.google.com");
- net::HttpRequestHeaders headers;
- provider.AppendHeaders(url, false, false, &headers);
- std::string variations;
- headers.GetHeader("X-Client-Data", &variations);
-
- std::set<VariationID> variation_ids;
- std::set<VariationID> trigger_ids;
- ASSERT_TRUE(ExtractVariationIds(variations, &variation_ids, &trigger_ids));
- EXPECT_TRUE(variation_ids.find(123) != variation_ids.end());
- EXPECT_TRUE(trigger_ids.find(456) != trigger_ids.end());
-}
-
-} // namespace variations
diff --git a/components/variations/net/variations_http_headers.cc b/components/variations/net/variations_http_headers.cc
new file mode 100644
index 0000000..632a0e0
--- /dev/null
+++ b/components/variations/net/variations_http_headers.cc
@@ -0,0 +1,98 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/variations/net/variations_http_headers.h"
+
+#include "base/strings/string_util.h"
+#include "components/google/core/browser/google_util.h"
+#include "components/variations/variations_http_header_provider.h"
+#include "net/http/http_request_headers.h"
+#include "url/gurl.h"
+
+namespace variations {
+
+namespace {
+
+const char* kSuffixesToSetHeadersFor[] = {
+ ".android.com",
+ ".doubleclick.com",
+ ".doubleclick.net",
+ ".ggpht.com",
+ ".googleadservices.com",
+ ".googleapis.com",
+ ".googlesyndication.com",
+ ".googleusercontent.com",
+ ".googlevideo.com",
+ ".gstatic.com",
+ ".ytimg.com",
+};
+
+const char kChromeUMAEnabled[] = "X-Chrome-UMA-Enabled";
+const char kClientData[] = "X-Client-Data";
+
+} // namespace
+
+void AppendVariationHeaders(const GURL& url,
+ bool incognito,
+ bool uma_enabled,
+ net::HttpRequestHeaders* headers) {
+ // Note the criteria for attaching client experiment headers:
+ // 1. We only transmit to Google owned domains which can evaluate experiments.
+ // 1a. These include hosts which have a standard postfix such as:
+ // *.doubleclick.net or *.googlesyndication.com or
+ // exactly www.googleadservices.com or
+ // international TLD domains *.google.<TLD> or *.youtube.<TLD>.
+ // 2. Only transmit for non-Incognito profiles.
+ // 3. For the X-Chrome-UMA-Enabled bit, only set it if UMA is in fact enabled
+ // for this install of Chrome.
+ // 4. For the X-Client-Data header, only include non-empty variation IDs.
+ if (incognito || !internal::ShouldAppendVariationHeaders(url))
+ return;
+
+ if (uma_enabled)
+ headers->SetHeaderIfMissing(kChromeUMAEnabled, "1");
+
+ const std::string variation_ids_header =
+ VariationsHttpHeaderProvider::GetInstance()->GetClientDataHeader();
+ if (!variation_ids_header.empty()) {
+ // Note that prior to M33 this header was named X-Chrome-Variations.
+ headers->SetHeaderIfMissing(kClientData, variation_ids_header);
+ }
+}
+
+std::set<std::string> GetVariationHeaderNames() {
+ std::set<std::string> headers;
+ headers.insert(kChromeUMAEnabled);
+ headers.insert(kClientData);
+ return headers;
+}
+
+namespace internal {
+
+// static
+bool ShouldAppendVariationHeaders(const GURL& url) {
+ if (google_util::IsGoogleDomainUrl(url, google_util::ALLOW_SUBDOMAIN,
+ google_util::ALLOW_NON_STANDARD_PORTS)) {
+ return true;
+ }
+
+ if (!url.is_valid() || !url.SchemeIsHTTPOrHTTPS())
+ return false;
+
+ // Some domains don't have international TLD extensions, so testing for them
+ // is very straight forward.
+ const std::string host = url.host();
+ for (size_t i = 0; i < arraysize(kSuffixesToSetHeadersFor); ++i) {
+ if (base::EndsWith(host, kSuffixesToSetHeadersFor[i],
+ base::CompareCase::INSENSITIVE_ASCII))
+ return true;
+ }
+
+ return google_util::IsYoutubeDomainUrl(url, google_util::ALLOW_SUBDOMAIN,
+ google_util::ALLOW_NON_STANDARD_PORTS);
+}
+
+} // namespace internal
+
+} // namespace variations
diff --git a/components/variations/net/variations_http_headers.h b/components/variations/net/variations_http_headers.h
new file mode 100644
index 0000000..d6280e5
--- /dev/null
+++ b/components/variations/net/variations_http_headers.h
@@ -0,0 +1,41 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VARIATIONS_NET_VARIATIONS_HTTP_HEADERS_H_
+#define COMPONENTS_VARIATIONS_NET_VARIATIONS_HTTP_HEADERS_H_
+
+#include <set>
+#include <string>
+
+namespace net {
+class HttpRequestHeaders;
+}
+
+class GURL;
+
+namespace variations {
+
+// Adds Chrome experiment and metrics state as custom headers to |headers|.
+// Some headers may not be set given the |incognito| mode or whether
+// the user has |uma_enabled|. Also, we never transmit headers to non-Google
+// sites, which is checked based on the destination |url|.
+void AppendVariationHeaders(const GURL& url,
+ bool incognito,
+ bool uma_enabled,
+ net::HttpRequestHeaders* headers);
+
+// Returns the HTTP header names which are added by AppendVariationHeaders().
+std::set<std::string> GetVariationHeaderNames();
+
+namespace internal {
+
+// Checks whether variation headers should be appended to requests to the
+// specified |url|. Returns true for google.<TLD> and youtube.<TLD> URLs.
+bool ShouldAppendVariationHeaders(const GURL& url);
+
+} // namespace internal
+
+} // namespace variations
+
+#endif // COMPONENTS_VARIATIONS_NET_VARIATIONS_HTTP_HEADERS_H_
diff --git a/components/variations/net/variations_http_headers_unittest.cc b/components/variations/net/variations_http_headers_unittest.cc
new file mode 100644
index 0000000..0f04c44
--- /dev/null
+++ b/components/variations/net/variations_http_headers_unittest.cc
@@ -0,0 +1,111 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/variations/net/variations_http_headers.h"
+
+#include "base/macros.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace variations {
+
+TEST(VariationsHttpHeadersTest, ShouldAppendHeaders) {
+ struct {
+ const char* url;
+ bool should_append_headers;
+ } cases[] = {
+ {"http://google.com", true},
+ {"http://www.google.com", true},
+ {"http://m.google.com", true},
+ {"http://google.ca", true},
+ {"https://google.ca", true},
+ {"http://google.co.uk", true},
+ {"http://google.co.uk:8080/", true},
+ {"http://www.google.co.uk:8080/", true},
+ {"http://google", false},
+
+ {"http://youtube.com", true},
+ {"http://www.youtube.com", true},
+ {"http://www.youtube.ca", true},
+ {"http://www.youtube.co.uk:8080/", true},
+ {"https://www.youtube.com", true},
+ {"http://youtube", false},
+
+ {"http://www.yahoo.com", false},
+
+ {"http://ad.doubleclick.net", true},
+ {"https://a.b.c.doubleclick.net", true},
+ {"https://a.b.c.doubleclick.net:8081", true},
+ {"http://www.doubleclick.com", true},
+ {"http://www.doubleclick.org", false},
+ {"http://www.doubleclick.net.com", false},
+ {"https://www.doubleclick.net.com", false},
+
+ {"http://ad.googlesyndication.com", true},
+ {"https://a.b.c.googlesyndication.com", true},
+ {"https://a.b.c.googlesyndication.com:8080", true},
+ {"http://www.doubleclick.edu", false},
+ {"http://www.googlesyndication.com.edu", false},
+ {"https://www.googlesyndication.com.com", false},
+
+ {"http://www.googleadservices.com", true},
+ {"http://www.googleadservices.com:8080", true},
+ {"https://www.googleadservices.com", true},
+ {"https://www.internal.googleadservices.com", true},
+ {"https://www2.googleadservices.com", true},
+ {"https://www.googleadservices.org", false},
+ {"https://www.googleadservices.com.co.uk", false},
+
+ {"http://WWW.ANDROID.COM", true},
+ {"http://www.android.com", true},
+ {"http://www.doubleclick.com", true},
+ {"http://www.doubleclick.net", true},
+ {"http://www.ggpht.com", true},
+ {"http://www.googleadservices.com", true},
+ {"http://www.googleapis.com", true},
+ {"http://www.googlesyndication.com", true},
+ {"http://www.googleusercontent.com", true},
+ {"http://www.googlevideo.com", true},
+ {"http://ssl.gstatic.com", true},
+ {"http://www.gstatic.com", true},
+ {"http://www.ytimg.com", true},
+ {"http://wwwytimg.com", false},
+ {"http://ytimg.com", false},
+
+ {"http://www.android.org", false},
+ {"http://www.doubleclick.org", false},
+ {"http://www.doubleclick.net", true},
+ {"http://www.ggpht.org", false},
+ {"http://www.googleadservices.org", false},
+ {"http://www.googleapis.org", false},
+ {"http://www.googlesyndication.org", false},
+ {"http://www.googleusercontent.org", false},
+ {"http://www.googlevideo.org", false},
+ {"http://ssl.gstatic.org", false},
+ {"http://www.gstatic.org", false},
+ {"http://www.ytimg.org", false},
+
+ {"http://a.b.android.com", true},
+ {"http://a.b.doubleclick.com", true},
+ {"http://a.b.doubleclick.net", true},
+ {"http://a.b.ggpht.com", true},
+ {"http://a.b.googleadservices.com", true},
+ {"http://a.b.googleapis.com", true},
+ {"http://a.b.googlesyndication.com", true},
+ {"http://a.b.googleusercontent.com", true},
+ {"http://a.b.googlevideo.com", true},
+ {"http://ssl.gstatic.com", true},
+ {"http://a.b.gstatic.com", true},
+ {"http://a.b.ytimg.com", true},
+ };
+
+ for (size_t i = 0; i < arraysize(cases); ++i) {
+ const GURL url(cases[i].url);
+ EXPECT_EQ(cases[i].should_append_headers,
+ internal::ShouldAppendVariationHeaders(url))
+ << url;
+ }
+}
+
+} // namespace variations
diff --git a/components/variations/synthetic_trials.cc b/components/variations/synthetic_trials.cc
new file mode 100644
index 0000000..228ca44
--- /dev/null
+++ b/components/variations/synthetic_trials.cc
@@ -0,0 +1,16 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/variations/synthetic_trials.h"
+
+namespace variations {
+
+SyntheticTrialGroup::SyntheticTrialGroup(uint32_t trial, uint32_t group) {
+ id.name = trial;
+ id.group = group;
+}
+
+SyntheticTrialGroup::~SyntheticTrialGroup() {}
+
+} // namespace variations
diff --git a/components/variations/synthetic_trials.h b/components/variations/synthetic_trials.h
new file mode 100644
index 0000000..b5b4240
--- /dev/null
+++ b/components/variations/synthetic_trials.h
@@ -0,0 +1,41 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VARIATIONS_SYNTHETIC_TRIALS_H_
+#define COMPONENTS_VARIATIONS_SYNTHETIC_TRIALS_H_
+
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/time/time.h"
+#include "components/variations/active_field_trials.h"
+
+namespace variations {
+
+// A Field Trial and its selected group, which represent a particular
+// Chrome configuration state. For example, the trial name could map to
+// a preference name, and the group name could map to a preference value.
+struct SyntheticTrialGroup {
+ public:
+ SyntheticTrialGroup(uint32_t trial, uint32_t group);
+ ~SyntheticTrialGroup();
+
+ ActiveGroupId id;
+ base::TimeTicks start_time;
+};
+
+// 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() {}
+};
+
+} // namespace variations
+
+#endif // COMPONENTS_VARIATIONS_SYNTHETIC_TRIALS_H_
diff --git a/components/variations/net/variations_http_header_provider.cc b/components/variations/variations_http_header_provider.cc
index 6754cef..316fe52 100644
--- a/components/variations/net/variations_http_header_provider.cc
+++ b/components/variations/variations_http_header_provider.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/variations/net/variations_http_header_provider.h"
+#include "components/variations/variations_http_header_provider.h"
#include <set>
#include <string>
@@ -14,60 +14,16 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
-#include "components/google/core/browser/google_util.h"
#include "components/variations/proto/client_variations.pb.h"
-#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
-#include "net/http/http_request_headers.h"
-#include "url/gurl.h"
namespace variations {
-namespace {
-
-const char* kSuffixesToSetHeadersFor[] = {
- ".android.com",
- ".doubleclick.com",
- ".doubleclick.net",
- ".ggpht.com",
- ".googleadservices.com",
- ".googleapis.com",
- ".googlesyndication.com",
- ".googleusercontent.com",
- ".googlevideo.com",
- ".gstatic.com",
- ".ytimg.com",
-};
-
-const char kChromeUMAEnabled[] = "X-Chrome-UMA-Enabled";
-const char kClientData[] = "X-Client-Data";
-
-} // namespace
-
+// static
VariationsHttpHeaderProvider* VariationsHttpHeaderProvider::GetInstance() {
return base::Singleton<VariationsHttpHeaderProvider>::get();
}
-void VariationsHttpHeaderProvider::AppendHeaders(
- const GURL& url,
- bool incognito,
- bool uma_enabled,
- net::HttpRequestHeaders* headers) {
- // Note the criteria for attaching client experiment headers:
- // 1. We only transmit to Google owned domains which can evaluate experiments.
- // 1a. These include hosts which have a standard postfix such as:
- // *.doubleclick.net or *.googlesyndication.com or
- // exactly www.googleadservices.com or
- // international TLD domains *.google.<TLD> or *.youtube.<TLD>.
- // 2. Only transmit for non-Incognito profiles.
- // 3. For the X-Chrome-UMA-Enabled bit, only set it if UMA is in fact enabled
- // for this install of Chrome.
- // 4. For the X-Client-Data header, only include non-empty variation IDs.
- if (incognito || !ShouldAppendHeaders(url))
- return;
-
- if (uma_enabled)
- headers->SetHeaderIfMissing(kChromeUMAEnabled, "1");
-
+std::string VariationsHttpHeaderProvider::GetClientDataHeader() {
// Lazily initialize the header, if not already done, before attempting to
// transmit it.
InitVariationIDsCacheIfNeeded();
@@ -77,11 +33,7 @@ void VariationsHttpHeaderProvider::AppendHeaders(
base::AutoLock scoped_lock(lock_);
variation_ids_header_copy = variation_ids_header_;
}
-
- if (!variation_ids_header_copy.empty()) {
- // Note that prior to M33 this header was named X-Chrome-Variations.
- headers->SetHeaderIfMissing(kClientData, variation_ids_header_copy);
- }
+ return variation_ids_header_copy;
}
bool VariationsHttpHeaderProvider::SetDefaultVariationIds(
@@ -98,7 +50,7 @@ bool VariationsHttpHeaderProvider::SetDefaultVariationIds(
bool trigger_id =
base::StartsWith(entry, "t", base::CompareCase::SENSITIVE);
// Remove the "t" prefix if it's there.
- base::StringPiece trimmed_entry = trigger_id ? entry.substr(1) : entry;
+ base::StringPiece trimmed_entry = trigger_id ? entry.substr(1) : entry;
int variation_id = 0;
if (!base::StringToInt(trimmed_entry, &variation_id)) {
@@ -114,14 +66,6 @@ bool VariationsHttpHeaderProvider::SetDefaultVariationIds(
return true;
}
-std::set<std::string> VariationsHttpHeaderProvider::GetVariationHeaderNames()
- const {
- std::set<std::string> headers;
- headers.insert(kChromeUMAEnabled);
- headers.insert(kClientData);
- return headers;
-}
-
void VariationsHttpHeaderProvider::ResetForTesting() {
base::AutoLock scoped_lock(lock_);
@@ -132,11 +76,9 @@ void VariationsHttpHeaderProvider::ResetForTesting() {
}
VariationsHttpHeaderProvider::VariationsHttpHeaderProvider()
- : variation_ids_cache_initialized_(false) {
-}
+ : variation_ids_cache_initialized_(false) {}
-VariationsHttpHeaderProvider::~VariationsHttpHeaderProvider() {
-}
+VariationsHttpHeaderProvider::~VariationsHttpHeaderProvider() {}
void VariationsHttpHeaderProvider::OnFieldTrialGroupFinalized(
const std::string& trial_name,
@@ -158,11 +100,11 @@ void VariationsHttpHeaderProvider::OnFieldTrialGroupFinalized(
}
void VariationsHttpHeaderProvider::OnSyntheticTrialsChanged(
- const std::vector<metrics::SyntheticTrialGroup>& groups) {
+ const std::vector<SyntheticTrialGroup>& groups) {
base::AutoLock scoped_lock(lock_);
synthetic_variation_ids_set_.clear();
- for (const metrics::SyntheticTrialGroup& group : groups) {
+ for (const SyntheticTrialGroup& group : groups) {
const VariationID id =
GetGoogleVariationIDFromHashes(GOOGLE_WEB_PROPERTIES, group.id);
if (id != EMPTY_ID)
@@ -188,15 +130,13 @@ void VariationsHttpHeaderProvider::InitVariationIDsCacheIfNeeded() {
for (base::FieldTrial::ActiveGroups::const_iterator it =
initial_groups.begin();
it != initial_groups.end(); ++it) {
- const VariationID id =
- GetGoogleVariationID(GOOGLE_WEB_PROPERTIES, it->trial_name,
- it->group_name);
+ const VariationID id = GetGoogleVariationID(GOOGLE_WEB_PROPERTIES,
+ it->trial_name, it->group_name);
if (id != EMPTY_ID)
variation_ids_set_.insert(id);
- const VariationID trigger_id =
- GetGoogleVariationID(GOOGLE_WEB_PROPERTIES_TRIGGER, it->trial_name,
- it->group_name);
+ const VariationID trigger_id = GetGoogleVariationID(
+ GOOGLE_WEB_PROPERTIES_TRIGGER, it->trial_name, it->group_name);
if (trigger_id != EMPTY_ID)
variation_trigger_ids_set_.insert(trigger_id);
}
@@ -204,10 +144,8 @@ void VariationsHttpHeaderProvider::InitVariationIDsCacheIfNeeded() {
UMA_HISTOGRAM_CUSTOM_COUNTS(
"Variations.HeaderConstructionTime",
- (base::TimeTicks::Now() - before_time).InMicroseconds(),
- 0,
- base::TimeDelta::FromSeconds(1).InMicroseconds(),
- 50);
+ (base::TimeTicks::Now() - before_time).InMicroseconds(), 0,
+ base::TimeDelta::FromSeconds(1).InMicroseconds(), 50);
variation_ids_cache_initialized_ = true;
}
@@ -265,27 +203,4 @@ void VariationsHttpHeaderProvider::UpdateVariationIDsHeaderValue() {
variation_ids_header_ = hashed;
}
-// static
-bool VariationsHttpHeaderProvider::ShouldAppendHeaders(const GURL& url) {
- if (google_util::IsGoogleDomainUrl(url, google_util::ALLOW_SUBDOMAIN,
- google_util::ALLOW_NON_STANDARD_PORTS)) {
- return true;
- }
-
- if (!url.is_valid() || !url.SchemeIsHTTPOrHTTPS())
- return false;
-
- // Some domains don't have international TLD extensions, so testing for them
- // is very straight forward.
- const std::string host = url.host();
- for (size_t i = 0; i < arraysize(kSuffixesToSetHeadersFor); ++i) {
- if (base::EndsWith(host, kSuffixesToSetHeadersFor[i],
- base::CompareCase::INSENSITIVE_ASCII))
- return true;
- }
-
- return google_util::IsYoutubeDomainUrl(url, google_util::ALLOW_SUBDOMAIN,
- google_util::ALLOW_NON_STANDARD_PORTS);
-}
-
} // namespace variations
diff --git a/components/variations/net/variations_http_header_provider.h b/components/variations/variations_http_header_provider.h
index 21f8659..18ff19d 100644
--- a/components/variations/net/variations_http_header_provider.h
+++ b/components/variations/variations_http_header_provider.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_VARIATIONS_NET_VARIATIONS_HTTP_HEADER_PROVIDER_H_
-#define COMPONENTS_VARIATIONS_NET_VARIATIONS_HTTP_HEADER_PROVIDER_H_
+#ifndef COMPONENTS_VARIATIONS_VARIATIONS_HTTP_HEADER_PROVIDER_H_
+#define COMPONENTS_VARIATIONS_VARIATIONS_HTTP_HEADER_PROVIDER_H_
#include <set>
#include <string>
@@ -13,21 +13,12 @@
#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/synthetic_trials.h"
#include "components/variations/variations_associated_data.h"
-namespace content {
-class ResourceContext;
-}
-
-namespace net {
-class HttpRequestHeaders;
-}
-
-class GURL;
-
namespace base {
-template <typename T> struct DefaultSingletonTraits;
+template <typename T>
+struct DefaultSingletonTraits;
}
namespace variations {
@@ -36,18 +27,13 @@ namespace variations {
// transmitted in custom HTTP request headers.
// This class is a thread-safe singleton.
class VariationsHttpHeaderProvider : public base::FieldTrialList::Observer,
- public metrics::SyntheticTrialObserver {
+ public SyntheticTrialObserver {
public:
static VariationsHttpHeaderProvider* GetInstance();
- // Adds Chrome experiment and metrics state as custom headers to |headers|.
- // Some headers may not be set given the |incognito| mode or whether
- // the user has |uma_enabled|. Also, we never transmit headers to non-Google
- // sites, which is checked based on the destination |url|.
- void AppendHeaders(const GURL& url,
- bool incognito,
- bool uma_enabled,
- net::HttpRequestHeaders* headers);
+ // Returns the value of the client data header, computing and caching it if
+ // necessary.
+ std::string GetClientDataHeader();
// Sets *additional* variation ids and trigger variation ids to be encoded in
// the X-Client-Data request header. This is intended for development use to
@@ -56,9 +42,6 @@ class VariationsHttpHeaderProvider : public base::FieldTrialList::Observer,
// with "t" it will be treated as a trigger experiment id.
bool SetDefaultVariationIds(const std::string& variation_ids);
- // Returns the HTTP header names which are added in this class.
- std::set<std::string> GetVariationHeaderNames() const;
-
// Resets any cached state for tests.
void ResetForTesting();
@@ -66,8 +49,6 @@ class VariationsHttpHeaderProvider : public base::FieldTrialList::Observer,
friend struct base::DefaultSingletonTraits<VariationsHttpHeaderProvider>;
FRIEND_TEST_ALL_PREFIXES(VariationsHttpHeaderProviderTest,
- ShouldAppendHeaders);
- FRIEND_TEST_ALL_PREFIXES(VariationsHttpHeaderProviderTest,
SetDefaultVariationIds_Valid);
FRIEND_TEST_ALL_PREFIXES(VariationsHttpHeaderProviderTest,
SetDefaultVariationIds_Invalid);
@@ -85,7 +66,7 @@ class VariationsHttpHeaderProvider : public base::FieldTrialList::Observer,
// metrics::SyntheticTrialObserver:
void OnSyntheticTrialsChanged(
- const std::vector<metrics::SyntheticTrialGroup>& groups) override;
+ const std::vector<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
@@ -97,10 +78,6 @@ class VariationsHttpHeaderProvider : public base::FieldTrialList::Observer,
// held.
void UpdateVariationIDsHeaderValue();
- // Checks whether variation headers should be appended to requests to the
- // specified |url|. Returns true for google.<TLD> and youtube.<TLD> URLs.
- static bool ShouldAppendHeaders(const GURL& url);
-
// Guards |variation_ids_cache_initialized_|, |variation_ids_set_| and
// |variation_ids_header_|.
base::Lock lock_;
@@ -127,4 +104,4 @@ class VariationsHttpHeaderProvider : public base::FieldTrialList::Observer,
} // namespace variations
-#endif // COMPONENTS_VARIATIONS_NET_VARIATIONS_HTTP_HEADER_PROVIDER_H_
+#endif // COMPONENTS_VARIATIONS_VARIATIONS_HTTP_HEADER_PROVIDER_H_
diff --git a/components/variations/variations_http_header_provider_unittest.cc b/components/variations/variations_http_header_provider_unittest.cc
new file mode 100644
index 0000000..22d5173
--- /dev/null
+++ b/components/variations/variations_http_header_provider_unittest.cc
@@ -0,0 +1,126 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/variations/variations_http_header_provider.h"
+
+#include <string>
+
+#include "base/base64.h"
+#include "base/message_loop/message_loop.h"
+#include "base/metrics/field_trial.h"
+#include "base/run_loop.h"
+#include "components/variations/entropy_provider.h"
+#include "components/variations/proto/client_variations.pb.h"
+#include "components/variations/variations_associated_data.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace variations {
+
+namespace {
+
+// Decodes the variations header and extracts the variation ids.
+bool ExtractVariationIds(const std::string& variations,
+ std::set<VariationID>* variation_ids,
+ std::set<VariationID>* trigger_ids) {
+ std::string serialized_proto;
+ if (!base::Base64Decode(variations, &serialized_proto))
+ return false;
+ ClientVariations proto;
+ if (!proto.ParseFromString(serialized_proto))
+ return false;
+ for (int i = 0; i < proto.variation_id_size(); ++i)
+ variation_ids->insert(proto.variation_id(i));
+ for (int i = 0; i < proto.trigger_variation_id_size(); ++i)
+ trigger_ids->insert(proto.trigger_variation_id(i));
+ return true;
+}
+
+scoped_refptr<base::FieldTrial> CreateTrialAndAssociateId(
+ const std::string& trial_name,
+ const std::string& default_group_name,
+ IDCollectionKey key,
+ VariationID id) {
+ scoped_refptr<base::FieldTrial> trial(
+ base::FieldTrialList::CreateFieldTrial(trial_name, default_group_name));
+
+ AssociateGoogleVariationID(key, trial->trial_name(), trial->group_name(), id);
+
+ return trial;
+}
+
+} // namespace
+
+class VariationsHttpHeaderProviderTest : public ::testing::Test {
+ public:
+ VariationsHttpHeaderProviderTest() {}
+
+ ~VariationsHttpHeaderProviderTest() override {}
+
+ void TearDown() override { testing::ClearAllVariationIDs(); }
+};
+
+TEST_F(VariationsHttpHeaderProviderTest, SetDefaultVariationIds_Valid) {
+ base::MessageLoop loop;
+ VariationsHttpHeaderProvider provider;
+
+ // Valid experiment ids.
+ EXPECT_TRUE(provider.SetDefaultVariationIds("12,456,t789"));
+ provider.InitVariationIDsCacheIfNeeded();
+ std::string variations = provider.GetClientDataHeader();
+ EXPECT_FALSE(variations.empty());
+ std::set<VariationID> variation_ids;
+ std::set<VariationID> trigger_ids;
+ ASSERT_TRUE(ExtractVariationIds(variations, &variation_ids, &trigger_ids));
+ EXPECT_TRUE(variation_ids.find(12) != variation_ids.end());
+ EXPECT_TRUE(variation_ids.find(456) != variation_ids.end());
+ EXPECT_TRUE(trigger_ids.find(789) != trigger_ids.end());
+ EXPECT_FALSE(variation_ids.find(789) != variation_ids.end());
+}
+
+TEST_F(VariationsHttpHeaderProviderTest, SetDefaultVariationIds_Invalid) {
+ base::MessageLoop loop;
+ VariationsHttpHeaderProvider provider;
+
+ // Invalid experiment ids.
+ EXPECT_FALSE(provider.SetDefaultVariationIds("abcd12,456"));
+ provider.InitVariationIDsCacheIfNeeded();
+ EXPECT_TRUE(provider.GetClientDataHeader().empty());
+
+ // Invalid trigger experiment id
+ EXPECT_FALSE(provider.SetDefaultVariationIds("12,tabc456"));
+ provider.InitVariationIDsCacheIfNeeded();
+ EXPECT_TRUE(provider.GetClientDataHeader().empty());
+}
+
+TEST_F(VariationsHttpHeaderProviderTest, OnFieldTrialGroupFinalized) {
+ base::MessageLoop loop;
+ base::FieldTrialList field_trial_list(nullptr);
+ VariationsHttpHeaderProvider provider;
+ provider.InitVariationIDsCacheIfNeeded();
+
+ const std::string default_name = "default";
+ scoped_refptr<base::FieldTrial> trial_1(CreateTrialAndAssociateId(
+ "t1", default_name, GOOGLE_WEB_PROPERTIES, 123));
+
+ ASSERT_EQ(default_name, trial_1->group_name());
+
+ scoped_refptr<base::FieldTrial> trial_2(CreateTrialAndAssociateId(
+ "t2", default_name, GOOGLE_WEB_PROPERTIES_TRIGGER, 456));
+
+ ASSERT_EQ(default_name, trial_2->group_name());
+
+ // Run the message loop to make sure OnFieldTrialGroupFinalized is called for
+ // the two field trials.
+ base::RunLoop().RunUntilIdle();
+
+ std::string variations = provider.GetClientDataHeader();
+
+ std::set<VariationID> variation_ids;
+ std::set<VariationID> trigger_ids;
+ ASSERT_TRUE(ExtractVariationIds(variations, &variation_ids, &trigger_ids));
+ EXPECT_TRUE(variation_ids.find(123) != variation_ids.end());
+ EXPECT_TRUE(trigger_ids.find(456) != trigger_ids.end());
+}
+
+} // namespace variations