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.
5 #include "components/variations/caching_permuted_entropy_provider.h"
9 #include "base/base64.h"
10 #include "base/logging.h"
11 #include "base/prefs/pref_registry_simple.h"
12 #include "base/prefs/pref_service.h"
13 #include "components/variations/pref_names.h"
17 CachingPermutedEntropyProvider::CachingPermutedEntropyProvider(
18 PrefService
* local_state
,
19 uint16 low_entropy_source
,
20 size_t low_entropy_source_max
)
21 : PermutedEntropyProvider(low_entropy_source
, low_entropy_source_max
),
22 local_state_(local_state
) {
26 CachingPermutedEntropyProvider::~CachingPermutedEntropyProvider() {
30 void CachingPermutedEntropyProvider::RegisterPrefs(
31 PrefRegistrySimple
* registry
) {
32 registry
->RegisterStringPref(
33 chrome_variations::prefs::kVariationsPermutedEntropyCache
, std::string());
37 void CachingPermutedEntropyProvider::ClearCache(PrefService
* local_state
) {
38 local_state
->ClearPref(
39 chrome_variations::prefs::kVariationsPermutedEntropyCache
);
42 uint16
CachingPermutedEntropyProvider::GetPermutedValue(
43 uint32 randomization_seed
) const {
44 DCHECK(thread_checker_
.CalledOnValidThread());
47 if (!FindValue(randomization_seed
, &value
)) {
48 value
= PermutedEntropyProvider::GetPermutedValue(randomization_seed
);
49 AddToCache(randomization_seed
, value
);
54 void CachingPermutedEntropyProvider::ReadFromLocalState() const {
55 const std::string base64_cache_data
= local_state_
->GetString(
56 chrome_variations::prefs::kVariationsPermutedEntropyCache
);
57 std::string cache_data
;
58 if (!base::Base64Decode(base64_cache_data
, &cache_data
) ||
59 !cache_
.ParseFromString(cache_data
)) {
60 local_state_
->ClearPref(
61 chrome_variations::prefs::kVariationsPermutedEntropyCache
);
66 void CachingPermutedEntropyProvider::UpdateLocalState() const {
67 std::string serialized
;
68 cache_
.SerializeToString(&serialized
);
70 std::string base64_encoded
;
71 base::Base64Encode(serialized
, &base64_encoded
);
72 local_state_
->SetString(
73 chrome_variations::prefs::kVariationsPermutedEntropyCache
,
77 void CachingPermutedEntropyProvider::AddToCache(uint32 randomization_seed
,
79 PermutedEntropyCache::Entry
* entry
;
80 const int kMaxSize
= 25;
81 if (cache_
.entry_size() >= kMaxSize
) {
82 // If the cache is full, evict the first entry, swapping later entries in
83 // to take its place. This effectively creates a FIFO cache, which is good
84 // enough here because the expectation is that there shouldn't be more than
85 // |kMaxSize| field trials at any given time, so eviction should happen very
86 // rarely, only as new trials are introduced, evicting old expired trials.
87 for (int i
= 1; i
< kMaxSize
; ++i
)
88 cache_
.mutable_entry()->SwapElements(i
- 1, i
);
89 entry
= cache_
.mutable_entry(kMaxSize
- 1);
91 entry
= cache_
.add_entry();
94 entry
->set_randomization_seed(randomization_seed
);
95 entry
->set_value(value
);
100 bool CachingPermutedEntropyProvider::FindValue(uint32 randomization_seed
,
101 uint16
* value
) const {
102 for (int i
= 0; i
< cache_
.entry_size(); ++i
) {
103 if (cache_
.entry(i
).randomization_seed() == randomization_seed
) {
104 *value
= cache_
.entry(i
).value();
111 } // namespace metrics