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", ¶ms)) { 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