Home | History | Annotate | Download | only in variations
      1 // Copyright 2013 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 CHROME_COMMON_METRICS_VARIATIONS_VARIATIONS_ASSOCIATED_DATA_H_
      6 #define CHROME_COMMON_METRICS_VARIATIONS_VARIATIONS_ASSOCIATED_DATA_H_
      7 
      8 #include <map>
      9 #include <string>
     10 
     11 #include "base/metrics/field_trial.h"
     12 #include "base/strings/string16.h"
     13 #include "chrome/common/metrics/variations/variation_ids.h"
     14 
     15 // This file provides various helpers that extend the functionality around
     16 // base::FieldTrial.
     17 //
     18 // This includes several simple APIs to handle getting and setting additional
     19 // data related to Chrome variations, such as parameters and Google variation
     20 // IDs. These APIs are meant to extend the base::FieldTrial APIs to offer extra
     21 // functionality that is not offered by the simpler base::FieldTrial APIs.
     22 //
     23 // The AssociateGoogleVariationID and AssociateVariationParams functions are
     24 // generally meant to be called by the VariationsService based on server-side
     25 // variation configs, but may also be used for client-only field trials by
     26 // invoking them directly after appending all the groups to a FieldTrial.
     27 //
     28 // Experiment code can then use the getter APIs to retrieve variation parameters
     29 // or IDs:
     30 //
     31 //  std::map<std::string, std::string> params;
     32 //  if (GetVariationParams("trial", &params)) {
     33 //    // use |params|
     34 //  }
     35 //
     36 //  std::string value = GetVariationParamValue("trial", "param_x");
     37 //  // use |value|, which will be "" if it does not exist
     38 //
     39 // VariationID id = GetGoogleVariationID(GOOGLE_WEB_PROPERTIES, "trial",
     40 //                                       "group1");
     41 // if (id != chrome_variations::kEmptyID) {
     42 //   // use |id|
     43 // }
     44 
     45 namespace chrome_variations {
     46 
     47 // The Unique ID of a trial and its active group, where the name and group
     48 // identifiers are hashes of the trial and group name strings.
     49 struct ActiveGroupId {
     50   uint32 name;
     51   uint32 group;
     52 };
     53 
     54 // Returns an ActiveGroupId struct for the given trial and group names.
     55 ActiveGroupId MakeActiveGroupId(const std::string& trial_name,
     56                                 const std::string& group_name);
     57 
     58 // We need to supply a Compare class for templates since ActiveGroupId is a
     59 // user-defined type.
     60 struct ActiveGroupIdCompare {
     61   bool operator() (const ActiveGroupId& lhs, const ActiveGroupId& rhs) const {
     62     // The group and name fields are just SHA-1 Hashes, so we just need to treat
     63     // them as IDs and do a less-than comparison. We test group first, since
     64     // name is more likely to collide.
     65     if (lhs.group != rhs.group)
     66       return lhs.group < rhs.group;
     67     return lhs.name < rhs.name;
     68   }
     69 };
     70 
     71 // A key into the Associate/Get methods for VariationIDs. This is used to create
     72 // separate ID associations for separate parties interested in VariationIDs.
     73 enum IDCollectionKey {
     74   // This collection is used by Google web properties, transmitted through the
     75   // X-Chrome-Variations header.
     76   GOOGLE_WEB_PROPERTIES,
     77   // This collection is used by Google update services, transmitted through the
     78   // Google Update experiment labels.
     79   GOOGLE_UPDATE_SERVICE,
     80   // The total count of collections.
     81   ID_COLLECTION_COUNT,
     82 };
     83 
     84 // Associate a chrome_variations::VariationID value with a FieldTrial group for
     85 // collection |key|. If an id was previously set for |trial_name| and
     86 // |group_name|, this does nothing. The group is denoted by |trial_name| and
     87 // |group_name|. This must be called whenever a FieldTrial is prepared (create
     88 // the trial and append groups) and needs to have a
     89 // chrome_variations::VariationID associated with it so Google servers can
     90 // recognize the FieldTrial. Thread safe.
     91 void AssociateGoogleVariationID(IDCollectionKey key,
     92                                 const std::string& trial_name,
     93                                 const std::string& group_name,
     94                                 VariationID id);
     95 
     96 // As above, but overwrites any previously set id. Thread safe.
     97 void AssociateGoogleVariationIDForce(IDCollectionKey key,
     98                                      const std::string& trial_name,
     99                                      const std::string& group_name,
    100                                      VariationID id);
    101 
    102 // Retrieve the chrome_variations::VariationID associated with a FieldTrial
    103 // group for collection |key|. The group is denoted by |trial_name| and
    104 // |group_name|. This will return chrome_variations::kEmptyID if there is
    105 // currently no associated ID for the named group. This API can be nicely
    106 // combined with FieldTrial::GetActiveFieldTrialGroups() to enumerate the
    107 // variation IDs for all active FieldTrial groups. Thread safe.
    108 VariationID GetGoogleVariationID(IDCollectionKey key,
    109                                  const std::string& trial_name,
    110                                  const std::string& group_name);
    111 
    112 // Associates the specified set of key-value |params| with the variation
    113 // specified by |trial_name| and |group_name|. Fails and returns false if the
    114 // specified variation already has params associated with it or the field trial
    115 // is already active (group() has been called on it). Thread safe.
    116 bool AssociateVariationParams(const std::string& trial_name,
    117                               const std::string& group_name,
    118                               const std::map<std::string, std::string>& params);
    119 
    120 // Retrieves the set of key-value |params| for the variation associated with
    121 // the specified field trial, based on its selected group. If the field trial
    122 // does not exist or its selected group does not have any parameters associated
    123 // with it, returns false and does not modify |params|. Calling this function
    124 // will result in the field trial being marked as active if found (i.e. group()
    125 // will be called on it), if it wasn't already. Currently, this information is
    126 // only available from the browser process. Thread safe.
    127 bool GetVariationParams(const std::string& trial_name,
    128                         std::map<std::string, std::string>* params);
    129 
    130 // Retrieves a specific parameter value corresponding to |param_name| for the
    131 // variation associated with the specified field trial, based on its selected
    132 // group. If the field trial does not exist or the specified parameter does not
    133 // exist, returns an empty string. Calling this function will result in the
    134 // field trial being marked as active if found (i.e. group() will be called on
    135 // it), if it wasn't already. Currently, this information is only available from
    136 // the browser process. Thread safe.
    137 std::string GetVariationParamValue(const std::string& trial_name,
    138                                    const std::string& param_name);
    139 
    140 // Expose some functions for testing.
    141 namespace testing {
    142 
    143 // Clears all of the mapped associations.
    144 void ClearAllVariationIDs();
    145 
    146 // Clears all of the associated params.
    147 void ClearAllVariationParams();
    148 
    149 }  // namespace testing
    150 
    151 }  // namespace chrome_variations
    152 
    153 #endif  // CHROME_COMMON_METRICS_VARIATIONS_VARIATIONS_ASSOCIATED_DATA_H_
    154