1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef COMPONENTS_VARIATIONS_VARIATIONS_HTTP_HEADER_PROVIDER_H_
6#define COMPONENTS_VARIATIONS_VARIATIONS_HTTP_HEADER_PROVIDER_H_
7
8#include <set>
9#include <string>
10
11#include "base/basictypes.h"
12#include "base/gtest_prod_util.h"
13#include "base/metrics/field_trial.h"
14#include "base/synchronization/lock.h"
15#include "components/variations/variations_associated_data.h"
16
17namespace content {
18class ResourceContext;
19}
20
21namespace net {
22class HttpRequestHeaders;
23}
24
25class GURL;
26
27template <typename T> struct DefaultSingletonTraits;
28
29namespace variations {
30
31// A helper class for maintaining client experiments and metrics state
32// transmitted in custom HTTP request headers.
33// This class is a thread-safe singleton.
34class VariationsHttpHeaderProvider : base::FieldTrialList::Observer {
35 public:
36  static VariationsHttpHeaderProvider* GetInstance();
37
38  // Adds Chrome experiment and metrics state as custom headers to |headers|.
39  // Some headers may not be set given the |incognito| mode or whether
40  // the user has |uma_enabled|.  Also, we never transmit headers to non-Google
41  // sites, which is checked based on the destination |url|.
42  void AppendHeaders(const GURL& url,
43                     bool incognito,
44                     bool uma_enabled,
45                     net::HttpRequestHeaders* headers);
46
47  // Sets *additional* variation ids and trigger variation ids to be encoded in
48  // the X-Client-Data request header.  This is intended for development use to
49  // force a server side experiment id.  |variation_ids| should be a
50  // comma-separated string of numeric experiment ids.  If an id is prefixed
51  // with "t" it will be treated as a trigger experiment id.
52  bool SetDefaultVariationIds(const std::string& variation_ids);
53
54 private:
55  friend struct DefaultSingletonTraits<VariationsHttpHeaderProvider>;
56
57  FRIEND_TEST_ALL_PREFIXES(VariationsHttpHeaderProviderTest,
58                           ShouldAppendHeaders);
59  FRIEND_TEST_ALL_PREFIXES(VariationsHttpHeaderProviderTest,
60                           SetDefaultVariationIds_Valid);
61  FRIEND_TEST_ALL_PREFIXES(VariationsHttpHeaderProviderTest,
62                           SetDefaultVariationIds_Invalid);
63  FRIEND_TEST_ALL_PREFIXES(VariationsHttpHeaderProviderTest,
64                           OnFieldTrialGroupFinalized);
65
66  VariationsHttpHeaderProvider();
67  virtual ~VariationsHttpHeaderProvider();
68
69  // base::FieldTrialList::Observer implementation.
70  // This will add the variation ID associated with |trial_name| and
71  // |group_name| to the variation ID cache.
72  virtual void OnFieldTrialGroupFinalized(
73      const std::string& trial_name,
74      const std::string& group_name) OVERRIDE;
75
76  // Prepares the variation IDs cache with initial values if not already done.
77  // This method also registers the caller with the FieldTrialList to receive
78  // new variation IDs.
79  void InitVariationIDsCacheIfNeeded();
80
81  // Takes whatever is currently in |variation_ids_set_| and recreates
82  // |variation_ids_header_| with it.  Assumes the the |lock_| is currently
83  // held.
84  void UpdateVariationIDsHeaderValue();
85
86  // Checks whether variation headers should be appended to requests to the
87  // specified |url|. Returns true for google.<TLD> and youtube.<TLD> URLs.
88  static bool ShouldAppendHeaders(const GURL& url);
89
90  // Guards |variation_ids_cache_initialized_|, |variation_ids_set_| and
91  // |variation_ids_header_|.
92  base::Lock lock_;
93
94  // Whether or not we've initialized the cache.
95  bool variation_ids_cache_initialized_;
96
97  // Keep a cache of variation IDs that are transmitted in headers to Google.
98  // This consists of a list of valid IDs, and the actual transmitted header.
99  std::set<VariationID> variation_ids_set_;
100  std::set<VariationID> variation_trigger_ids_set_;
101
102  // Provides the google experiment ids forced from command line.
103  std::set<VariationID> default_variation_ids_set_;
104  std::set<VariationID> default_trigger_id_set_;
105
106  std::string variation_ids_header_;
107
108  DISALLOW_COPY_AND_ASSIGN(VariationsHttpHeaderProvider);
109};
110
111}  // namespace variations
112
113#endif  // COMPONENTS_VARIATIONS_VARIATIONS_HTTP_HEADER_PROVIDER_H_
114