12385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
22385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Use of this source code is governed by a BSD-style license that can be
32385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// found in the LICENSE file.
42385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
52385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#ifndef CHROME_COMMON_METRICS_VARIATIONS_VARIATIONS_ASSOCIATED_DATA_H_
62385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#define CHROME_COMMON_METRICS_VARIATIONS_VARIATIONS_ASSOCIATED_DATA_H_
72385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
82385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include <map>
92385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include <string>
102385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
112385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "base/metrics/field_trial.h"
122385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "base/strings/string16.h"
132385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/common/metrics/variations/variation_ids.h"
142385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
152385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// This file provides various helpers that extend the functionality around
162385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// base::FieldTrial.
172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch//
182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// This includes several simple APIs to handle getting and setting additional
192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// data related to Chrome variations, such as parameters and Google variation
202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// IDs. These APIs are meant to extend the base::FieldTrial APIs to offer extra
212385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// functionality that is not offered by the simpler base::FieldTrial APIs.
222385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch//
232385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// The AssociateGoogleVariationID and AssociateVariationParams functions are
242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// generally meant to be called by the VariationsService based on server-side
252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// variation configs, but may also be used for client-only field trials by
262385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// invoking them directly after appending all the groups to a FieldTrial.
272385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch//
282385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Experiment code can then use the getter APIs to retrieve variation parameters
292385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// or IDs:
302385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch//
312385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch//  std::map<std::string, std::string> params;
322385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch//  if (GetVariationParams("trial", &params)) {
332385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch//    // use |params|
342385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch//  }
352385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch//
362385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch//  std::string value = GetVariationParamValue("trial", "param_x");
372385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch//  // use |value|, which will be "" if it does not exist
382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch//
392385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// VariationID id = GetGoogleVariationID(GOOGLE_WEB_PROPERTIES, "trial",
402385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch//                                       "group1");
412385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// if (id != chrome_variations::kEmptyID) {
422385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch//   // use |id|
432385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// }
442385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
452385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochnamespace chrome_variations {
462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
472385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// The Unique ID of a trial and its active group, where the name and group
482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// identifiers are hashes of the trial and group name strings.
492385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochstruct ActiveGroupId {
502385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  uint32 name;
512385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  uint32 group;
522385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch};
532385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
542385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Returns an ActiveGroupId struct for the given trial and group names.
552385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochActiveGroupId MakeActiveGroupId(const std::string& trial_name,
562385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                const std::string& group_name);
572385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
582385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// We need to supply a Compare class for templates since ActiveGroupId is a
592385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// user-defined type.
602385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochstruct ActiveGroupIdCompare {
612385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  bool operator() (const ActiveGroupId& lhs, const ActiveGroupId& rhs) const {
622385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    // The group and name fields are just SHA-1 Hashes, so we just need to treat
632385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    // them as IDs and do a less-than comparison. We test group first, since
642385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    // name is more likely to collide.
652385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    if (lhs.group != rhs.group)
662385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      return lhs.group < rhs.group;
672385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    return lhs.name < rhs.name;
682385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  }
692385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch};
702385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
712385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// A key into the Associate/Get methods for VariationIDs. This is used to create
722385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// separate ID associations for separate parties interested in VariationIDs.
732385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochenum IDCollectionKey {
742385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // This collection is used by Google web properties, transmitted through the
752385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // X-Chrome-Variations header.
762385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  GOOGLE_WEB_PROPERTIES,
772385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // This collection is used by Google update services, transmitted through the
782385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // Google Update experiment labels.
792385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  GOOGLE_UPDATE_SERVICE,
802385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // The total count of collections.
812385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  ID_COLLECTION_COUNT,
822385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch};
832385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
842385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Associate a chrome_variations::VariationID value with a FieldTrial group for
852385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// collection |key|. If an id was previously set for |trial_name| and
862385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// |group_name|, this does nothing. The group is denoted by |trial_name| and
872385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// |group_name|. This must be called whenever a FieldTrial is prepared (create
882385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// the trial and append groups) and needs to have a
892385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// chrome_variations::VariationID associated with it so Google servers can
902385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// recognize the FieldTrial. Thread safe.
912385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid AssociateGoogleVariationID(IDCollectionKey key,
922385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                const std::string& trial_name,
932385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                const std::string& group_name,
942385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                VariationID id);
952385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
962385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// As above, but overwrites any previously set id. Thread safe.
972385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid AssociateGoogleVariationIDForce(IDCollectionKey key,
982385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                     const std::string& trial_name,
992385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                     const std::string& group_name,
1002385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                     VariationID id);
1012385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1022385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Retrieve the chrome_variations::VariationID associated with a FieldTrial
1032385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// group for collection |key|. The group is denoted by |trial_name| and
1042385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// |group_name|. This will return chrome_variations::kEmptyID if there is
1052385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// currently no associated ID for the named group. This API can be nicely
1062385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// combined with FieldTrial::GetActiveFieldTrialGroups() to enumerate the
1072385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// variation IDs for all active FieldTrial groups. Thread safe.
1082385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochVariationID GetGoogleVariationID(IDCollectionKey key,
1092385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                 const std::string& trial_name,
1102385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                 const std::string& group_name);
1112385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1122385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Associates the specified set of key-value |params| with the variation
1132385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// specified by |trial_name| and |group_name|. Fails and returns false if the
1142385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// specified variation already has params associated with it or the field trial
1152385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// is already active (group() has been called on it). Thread safe.
1162385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochbool AssociateVariationParams(const std::string& trial_name,
1172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                              const std::string& group_name,
1182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                              const std::map<std::string, std::string>& params);
1192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Retrieves the set of key-value |params| for the variation associated with
1212385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// the specified field trial, based on its selected group. If the field trial
1222385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// does not exist or its selected group does not have any parameters associated
1232385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// with it, returns false and does not modify |params|. Calling this function
1242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// will result in the field trial being marked as active if found (i.e. group()
1252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// will be called on it), if it wasn't already. Currently, this information is
1262385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// only available from the browser process. Thread safe.
1272385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochbool GetVariationParams(const std::string& trial_name,
1282385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                        std::map<std::string, std::string>* params);
1292385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1302385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Retrieves a specific parameter value corresponding to |param_name| for the
1312385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// variation associated with the specified field trial, based on its selected
1322385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// group. If the field trial does not exist or the specified parameter does not
1332385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// exist, returns an empty string. Calling this function will result in the
1342385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// field trial being marked as active if found (i.e. group() will be called on
1352385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// it), if it wasn't already. Currently, this information is only available from
1362385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// the browser process. Thread safe.
1372385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochstd::string GetVariationParamValue(const std::string& trial_name,
1382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                   const std::string& param_name);
1392385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1404311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch// Expose some functions for testing.
1412385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochnamespace testing {
1422385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1432385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Clears all of the mapped associations.
1442385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid ClearAllVariationIDs();
1452385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1464311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch// Clears all of the associated params.
1474311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdochvoid ClearAllVariationParams();
1484311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch
1492385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}  // namespace testing
1502385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1512385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}  // namespace chrome_variations
1522385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1532385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#endif  // CHROME_COMMON_METRICS_VARIATIONS_VARIATIONS_ASSOCIATED_DATA_H_
154