diff options
author | asvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-29 18:03:22 +0000 |
---|---|---|
committer | asvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-29 18:03:22 +0000 |
commit | 50ae9f1c73aaa89c137ad74bf75798ee4b0059f7 (patch) | |
tree | 44687f9efda1114a9874381e35ee08019e3b11d4 /components/variations/variations_associated_data.cc | |
parent | 67f73767318e1eb57ee8c036881166bd6629b1c1 (diff) | |
download | chromium_src-50ae9f1c73aaa89c137ad74bf75798ee4b0059f7.zip chromium_src-50ae9f1c73aaa89c137ad74bf75798ee4b0059f7.tar.gz chromium_src-50ae9f1c73aaa89c137ad74bf75798ee4b0059f7.tar.bz2 |
Create a variations component, so that it can be re-used.
Moving this code out of chrome/ paves the way for server-controlled system
field trials on ChromeOS. This allows building a new ChromeOS daemon binary
that depends on the new variations target, without needing to depend on all of
chrome/.
This CL moves several files from chrome/common/metrics and
chrome/browser/metrics into a separate component/variations target and
updates all the include paths referencing these. It does not do additional
cleanup, such as changing namespaces - this is left for a follow-up cleanup
CL.
BUG=266007
TEST=Existing unit tests.
R=joi@chromium.org, jwd@chromium.org, sky@chromium.org
Review URL: https://codereview.chromium.org/23097007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@220339 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components/variations/variations_associated_data.cc')
-rw-r--r-- | components/variations/variations_associated_data.cc | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/components/variations/variations_associated_data.cc b/components/variations/variations_associated_data.cc new file mode 100644 index 0000000..64a6d6e --- /dev/null +++ b/components/variations/variations_associated_data.cc @@ -0,0 +1,236 @@ +// Copyright 2013 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_associated_data.h" + +#include <map> +#include <utility> +#include <vector> + +#include "base/memory/singleton.h" +#include "components/variations/metrics_util.h" + +namespace chrome_variations { + +namespace { + +// The internal singleton accessor for the map, used to keep it thread-safe. +class GroupMapAccessor { + public: + typedef std::map<ActiveGroupId, VariationID, ActiveGroupIdCompare> + GroupToIDMap; + + // Retrieve the singleton. + static GroupMapAccessor* GetInstance() { + return Singleton<GroupMapAccessor>::get(); + } + + // Note that this normally only sets the ID for a group the first time, unless + // |force| is set to true, in which case it will always override it. + void AssociateID(IDCollectionKey key, + const ActiveGroupId& group_identifier, + const VariationID id, + const bool force) { +#if !defined(NDEBUG) + // Validate that all collections with this |group_identifier| have the same + // associated ID. + DCHECK_EQ(2, ID_COLLECTION_COUNT); + IDCollectionKey other_key = GOOGLE_WEB_PROPERTIES; + if (key == GOOGLE_WEB_PROPERTIES) + other_key = GOOGLE_UPDATE_SERVICE; + VariationID other_id = GetID(other_key, group_identifier); + DCHECK(other_id == EMPTY_ID || other_id == id); +#endif + + base::AutoLock scoped_lock(lock_); + + GroupToIDMap* group_to_id_map = GetGroupToIDMap(key); + if (force || + group_to_id_map->find(group_identifier) == group_to_id_map->end()) + (*group_to_id_map)[group_identifier] = id; + } + + VariationID GetID(IDCollectionKey key, + const ActiveGroupId& group_identifier) { + base::AutoLock scoped_lock(lock_); + GroupToIDMap* group_to_id_map = GetGroupToIDMap(key); + GroupToIDMap::const_iterator it = group_to_id_map->find(group_identifier); + if (it == group_to_id_map->end()) + return EMPTY_ID; + return it->second; + } + + void ClearAllMapsForTesting() { + base::AutoLock scoped_lock(lock_); + + for (int i = 0; i < ID_COLLECTION_COUNT; ++i) { + GroupToIDMap* map = GetGroupToIDMap(static_cast<IDCollectionKey>(i)); + DCHECK(map); + map->clear(); + } + } + + private: + friend struct DefaultSingletonTraits<GroupMapAccessor>; + + // Retrieves the GroupToIDMap for |key|. + GroupToIDMap* GetGroupToIDMap(IDCollectionKey key) { + return &group_to_id_maps_[key]; + } + + GroupMapAccessor() { + group_to_id_maps_.resize(ID_COLLECTION_COUNT); + } + ~GroupMapAccessor() {} + + base::Lock lock_; + std::vector<GroupToIDMap> group_to_id_maps_; + + DISALLOW_COPY_AND_ASSIGN(GroupMapAccessor); +}; + +// Singleton helper class that keeps track of the parameters of all variations +// and ensures access to these is thread-safe. +class VariationsParamAssociator { + public: + typedef std::pair<std::string, std::string> VariationKey; + typedef std::map<std::string, std::string> VariationParams; + + // Retrieve the singleton. + static VariationsParamAssociator* GetInstance() { + return Singleton<VariationsParamAssociator>::get(); + } + + bool AssociateVariationParams(const std::string& trial_name, + const std::string& group_name, + const VariationParams& params) { + base::AutoLock scoped_lock(lock_); + + if (IsFieldTrialActive(trial_name)) + return false; + + const VariationKey key(trial_name, group_name); + if (ContainsKey(variation_params_, key)) + return false; + + variation_params_[key] = params; + return true; + } + + bool GetVariationParams(const std::string& trial_name, + VariationParams* params) { + base::AutoLock scoped_lock(lock_); + + const std::string group_name = + base::FieldTrialList::FindFullName(trial_name); + const VariationKey key(trial_name, group_name); + if (!ContainsKey(variation_params_, key)) + return false; + + *params = variation_params_[key]; + return true; + } + + void ClearAllParamsForTesting() { + base::AutoLock scoped_lock(lock_); + variation_params_.clear(); + } + + private: + friend struct DefaultSingletonTraits<VariationsParamAssociator>; + + VariationsParamAssociator() {} + ~VariationsParamAssociator() {} + + // Tests whether a field trial is active (i.e. group() has been called on it). + // TODO(asvitkine): Expose this as an API on base::FieldTrial. + bool IsFieldTrialActive(const std::string& trial_name) { + base::FieldTrial::ActiveGroups active_groups; + base::FieldTrialList::GetActiveFieldTrialGroups(&active_groups); + for (size_t i = 0; i < active_groups.size(); ++i) { + if (active_groups[i].trial_name == trial_name) + return true; + } + return false; + } + + base::Lock lock_; + std::map<VariationKey, VariationParams> variation_params_; + + DISALLOW_COPY_AND_ASSIGN(VariationsParamAssociator); +}; + +} // namespace + +ActiveGroupId MakeActiveGroupId(const std::string& trial_name, + const std::string& group_name) { + ActiveGroupId id; + id.name = metrics::HashName(trial_name); + id.group = metrics::HashName(group_name); + return id; +} + +void AssociateGoogleVariationID(IDCollectionKey key, + const std::string& trial_name, + const std::string& group_name, + VariationID id) { + GroupMapAccessor::GetInstance()->AssociateID( + key, MakeActiveGroupId(trial_name, group_name), id, false); +} + +void AssociateGoogleVariationIDForce(IDCollectionKey key, + const std::string& trial_name, + const std::string& group_name, + VariationID id) { + GroupMapAccessor::GetInstance()->AssociateID( + key, MakeActiveGroupId(trial_name, group_name), id, true); +} + +VariationID GetGoogleVariationID(IDCollectionKey key, + const std::string& trial_name, + const std::string& group_name) { + return GroupMapAccessor::GetInstance()->GetID( + key, MakeActiveGroupId(trial_name, group_name)); +} + +bool AssociateVariationParams( + const std::string& trial_name, + const std::string& group_name, + const std::map<std::string, std::string>& params) { + return VariationsParamAssociator::GetInstance()->AssociateVariationParams( + trial_name, group_name, params); +} + +bool GetVariationParams(const std::string& trial_name, + std::map<std::string, std::string>* params) { + return VariationsParamAssociator::GetInstance()->GetVariationParams( + trial_name, params); +} + +std::string GetVariationParamValue(const std::string& trial_name, + const std::string& param_name) { + std::map<std::string, std::string> params; + if (GetVariationParams(trial_name, ¶ms)) { + std::map<std::string, std::string>::iterator it = params.find(param_name); + if (it != params.end()) + return it->second; + } + return std::string(); +} + +// Functions below are exposed for testing explicitly behind this namespace. +// They simply wrap existing functions in this file. +namespace testing { + +void ClearAllVariationIDs() { + GroupMapAccessor::GetInstance()->ClearAllMapsForTesting(); +} + +void ClearAllVariationParams() { + VariationsParamAssociator::GetInstance()->ClearAllParamsForTesting(); +} + +} // namespace testing + +} // namespace chrome_variations |