summaryrefslogtreecommitdiff
path: root/chromium/components/variations
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2022-02-04 17:20:24 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2022-02-12 08:15:25 +0000
commit8fa0776f1f79e91fc9c0b9c1ba11a0a29c05196b (patch)
tree788d8d7549712682703a0310ca4a0f0860d4802b /chromium/components/variations
parent606d85f2a5386472314d39923da28c70c60dc8e7 (diff)
downloadqtwebengine-chromium-8fa0776f1f79e91fc9c0b9c1ba11a0a29c05196b.tar.gz
BASELINE: Update Chromium to 98.0.4758.90
Change-Id: Ib7c41539bf8a8e0376bd639f27d68294de90f3c8 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/components/variations')
-rw-r--r--chromium/components/variations/BUILD.gn1
-rw-r--r--chromium/components/variations/DEPS1
-rw-r--r--chromium/components/variations/child_process_field_trial_syncer.h1
-rw-r--r--chromium/components/variations/child_process_field_trial_syncer_unittest.cc2
-rw-r--r--chromium/components/variations/client_filterable_state.h1
-rw-r--r--chromium/components/variations/entropy_provider.h1
-rw-r--r--chromium/components/variations/entropy_provider_unittest.cc1
-rw-r--r--chromium/components/variations/field_trial_config/field_trial_util_unittest.cc1
-rw-r--r--chromium/components/variations/hashing_unittest.cc1
-rw-r--r--chromium/components/variations/metrics.cc17
-rw-r--r--chromium/components/variations/metrics.h38
-rw-r--r--chromium/components/variations/net/variations_command_line_unittest.cc1
-rw-r--r--chromium/components/variations/net/variations_http_headers.cc14
-rw-r--r--chromium/components/variations/net/variations_http_headers.h3
-rw-r--r--chromium/components/variations/net/variations_http_headers_unittest.cc1
-rw-r--r--chromium/components/variations/platform_field_trials.h4
-rw-r--r--chromium/components/variations/pref_names.cc6
-rw-r--r--chromium/components/variations/pref_names.h2
-rw-r--r--chromium/components/variations/processed_study.h3
-rw-r--r--chromium/components/variations/service/safe_seed_manager.cc8
-rw-r--r--chromium/components/variations/service/safe_seed_manager.h13
-rw-r--r--chromium/components/variations/service/safe_seed_manager_unittest.cc39
-rw-r--r--chromium/components/variations/service/ui_string_overrider.h2
-rw-r--r--chromium/components/variations/service/ui_string_overrider_unittest.cc1
-rw-r--r--chromium/components/variations/service/variations_field_trial_creator.cc161
-rw-r--r--chromium/components/variations/service/variations_field_trial_creator.h34
-rw-r--r--chromium/components/variations/service/variations_field_trial_creator_unittest.cc426
-rw-r--r--chromium/components/variations/service/variations_safe_mode_constants.cc12
-rw-r--r--chromium/components/variations/service/variations_safe_mode_constants.h2
-rw-r--r--chromium/components/variations/service/variations_service.cc30
-rw-r--r--chromium/components/variations/service/variations_service.h20
-rw-r--r--chromium/components/variations/service/variations_service_unittest.cc4
-rw-r--r--chromium/components/variations/study_filtering_unittest.cc1
-rw-r--r--chromium/components/variations/synthetic_trial_registry_unittest.cc4
-rw-r--r--chromium/components/variations/synthetic_trials_active_group_id_provider.h1
-rw-r--r--chromium/components/variations/variations_associated_data.cc1
-rw-r--r--chromium/components/variations/variations_associated_data_unittest.cc1
-rw-r--r--chromium/components/variations/variations_crash_keys_chromeos.h2
-rw-r--r--chromium/components/variations/variations_ids_provider.h4
-rw-r--r--chromium/components/variations/variations_params_manager.h3
-rw-r--r--chromium/components/variations/variations_request_scheduler.h1
-rw-r--r--chromium/components/variations/variations_request_scheduler_mobile.h10
-rw-r--r--chromium/components/variations/variations_seed_processor.cc9
-rw-r--r--chromium/components/variations/variations_seed_processor.h1
-rw-r--r--chromium/components/variations/variations_seed_processor_unittest.cc28
-rw-r--r--chromium/components/variations/variations_seed_simulator.h1
-rw-r--r--chromium/components/variations/variations_seed_simulator_unittest.cc1
-rw-r--r--chromium/components/variations/variations_seed_store.cc339
-rw-r--r--chromium/components/variations/variations_seed_store.h8
-rw-r--r--chromium/components/variations/variations_seed_store_unittest.cc348
-rw-r--r--chromium/components/variations/variations_test_utils_unittest.cc8
51 files changed, 820 insertions, 802 deletions
diff --git a/chromium/components/variations/BUILD.gn b/chromium/components/variations/BUILD.gn
index e289f6b3a03..406e48daceb 100644
--- a/chromium/components/variations/BUILD.gn
+++ b/chromium/components/variations/BUILD.gn
@@ -128,6 +128,7 @@ component("variations") {
"//build:chromeos_buildflags",
"//components/crash/core/common:crash_key",
"//components/prefs",
+ "//components/version_info",
"//crypto",
"//third_party/protobuf:protobuf_lite",
"//third_party/zlib/google:compression_utils",
diff --git a/chromium/components/variations/DEPS b/chromium/components/variations/DEPS
index 6cbcd541878..aacb6bfa9f9 100644
--- a/chromium/components/variations/DEPS
+++ b/chromium/components/variations/DEPS
@@ -8,6 +8,7 @@ include_rules = [
"+components/metrics",
"+components/prefs",
"+components/variations",
+ "+components/version_info",
"+crypto",
"-net",
"+third_party/protobuf",
diff --git a/chromium/components/variations/child_process_field_trial_syncer.h b/chromium/components/variations/child_process_field_trial_syncer.h
index d3cd5e41090..d01575a1f94 100644
--- a/chromium/components/variations/child_process_field_trial_syncer.h
+++ b/chromium/components/variations/child_process_field_trial_syncer.h
@@ -10,7 +10,6 @@
#include "base/callback.h"
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/metrics/field_trial.h"
#include "base/threading/thread_local.h"
diff --git a/chromium/components/variations/child_process_field_trial_syncer_unittest.cc b/chromium/components/variations/child_process_field_trial_syncer_unittest.cc
index bab525295c6..7f8c3a4621b 100644
--- a/chromium/components/variations/child_process_field_trial_syncer_unittest.cc
+++ b/chromium/components/variations/child_process_field_trial_syncer_unittest.cc
@@ -22,7 +22,7 @@ TEST(ChildProcessFieldTrialSyncerTest, FieldTrialState) {
// We don't use the descriptor here anyways so it's ok to pass -1.
base::FieldTrialList::CreateTrialsFromCommandLine(
- *base::CommandLine::ForCurrentProcess(), "field_trial_handle_switch", -1);
+ *base::CommandLine::ForCurrentProcess(), -1);
base::FieldTrial* trial1 = base::FieldTrialList::CreateFieldTrial("A", "G1");
base::FieldTrial* trial2 = base::FieldTrialList::CreateFieldTrial("B", "G2");
diff --git a/chromium/components/variations/client_filterable_state.h b/chromium/components/variations/client_filterable_state.h
index 800c9371ffe..10da00095b1 100644
--- a/chromium/components/variations/client_filterable_state.h
+++ b/chromium/components/variations/client_filterable_state.h
@@ -9,7 +9,6 @@
#include "base/callback.h"
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/time/time.h"
#include "base/version.h"
#include "components/variations/proto/study.pb.h"
diff --git a/chromium/components/variations/entropy_provider.h b/chromium/components/variations/entropy_provider.h
index 23273fe0e19..1195036cf25 100644
--- a/chromium/components/variations/entropy_provider.h
+++ b/chromium/components/variations/entropy_provider.h
@@ -14,7 +14,6 @@
#include "base/compiler_specific.h"
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/metrics/field_trial.h"
namespace variations {
diff --git a/chromium/components/variations/entropy_provider_unittest.cc b/chromium/components/variations/entropy_provider_unittest.cc
index add104fc13d..56d202c2e32 100644
--- a/chromium/components/variations/entropy_provider_unittest.cc
+++ b/chromium/components/variations/entropy_provider_unittest.cc
@@ -14,7 +14,6 @@
#include "base/cxx17_backports.h"
#include "base/guid.h"
-#include "base/macros.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/scoped_field_trial_list_resetter.h"
diff --git a/chromium/components/variations/field_trial_config/field_trial_util_unittest.cc b/chromium/components/variations/field_trial_config/field_trial_util_unittest.cc
index 667d4452dee..22902f6ddc3 100644
--- a/chromium/components/variations/field_trial_config/field_trial_util_unittest.cc
+++ b/chromium/components/variations/field_trial_config/field_trial_util_unittest.cc
@@ -10,7 +10,6 @@
#include "base/command_line.h"
#include "base/cxx17_backports.h"
-#include "base/macros.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/utf_string_conversions.h"
diff --git a/chromium/components/variations/hashing_unittest.cc b/chromium/components/variations/hashing_unittest.cc
index 125581aa279..1c5e7add116 100644
--- a/chromium/components/variations/hashing_unittest.cc
+++ b/chromium/components/variations/hashing_unittest.cc
@@ -8,7 +8,6 @@
#include <stdint.h>
#include "base/cxx17_backports.h"
-#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace variations {
diff --git a/chromium/components/variations/metrics.cc b/chromium/components/variations/metrics.cc
index b876460632e..3f57768060e 100644
--- a/chromium/components/variations/metrics.cc
+++ b/chromium/components/variations/metrics.cc
@@ -26,28 +26,27 @@ void RecordLoadSafeSeedResult(LoadSeedResult state) {
}
void RecordStoreSeedResult(StoreSeedResult result) {
- UMA_HISTOGRAM_ENUMERATION("Variations.SeedStoreResult", result,
- StoreSeedResult::ENUM_SIZE);
+ base::UmaHistogramEnumeration("Variations.SeedStoreResult", result);
}
void ReportUnsupportedSeedFormatError() {
- RecordStoreSeedResult(StoreSeedResult::FAILED_UNSUPPORTED_SEED_FORMAT);
+ RecordStoreSeedResult(StoreSeedResult::kFailedUnsupportedSeedFormat);
}
void RecordStoreSafeSeedResult(StoreSeedResult result) {
- UMA_HISTOGRAM_ENUMERATION("Variations.SafeMode.StoreSafeSeed.Result", result,
- StoreSeedResult::ENUM_SIZE);
+ base::UmaHistogramEnumeration("Variations.SafeMode.StoreSafeSeed.Result",
+ result);
}
void RecordSeedInstanceManipulations(const InstanceManipulations& im) {
if (im.delta_compressed && im.gzip_compressed) {
- RecordStoreSeedResult(StoreSeedResult::GZIP_DELTA_COUNT);
+ RecordStoreSeedResult(StoreSeedResult::kGzipDeltaCount);
} else if (im.delta_compressed) {
- RecordStoreSeedResult(StoreSeedResult::NON_GZIP_DELTA_COUNT);
+ RecordStoreSeedResult(StoreSeedResult::kNonGzipDeltaCount);
} else if (im.gzip_compressed) {
- RecordStoreSeedResult(StoreSeedResult::GZIP_FULL_COUNT);
+ RecordStoreSeedResult(StoreSeedResult::kGzipFullCount);
} else {
- RecordStoreSeedResult(StoreSeedResult::NON_GZIP_FULL_COUNT);
+ RecordStoreSeedResult(StoreSeedResult::kNonGzipFullCount);
}
}
diff --git a/chromium/components/variations/metrics.h b/chromium/components/variations/metrics.h
index ebf5be97d6e..0bae191fc94 100644
--- a/chromium/components/variations/metrics.h
+++ b/chromium/components/variations/metrics.h
@@ -44,29 +44,31 @@ enum class LoadSeedResult {
};
// The result of attempting to store a variations seed received from the server.
-// Note: UMA histogram enum - don't re-order or remove entries.
+//
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
enum class StoreSeedResult {
- SUCCESS,
- FAILED_EMPTY,
- FAILED_PARSE,
- FAILED_SIGNATURE,
- FAILED_GZIP,
- DELTA_COUNT_OBSOLETE,
- FAILED_DELTA_READ_SEED,
- FAILED_DELTA_APPLY,
- FAILED_DELTA_STORE,
- FAILED_UNGZIP,
- FAILED_EMPTY_GZIP_CONTENTS,
- FAILED_UNSUPPORTED_SEED_FORMAT,
+ kSuccess = 0,
+ // kFailedEmpty = 1, // Deprecated.
+ kFailedParse = 2,
+ kFailedSignature = 3,
+ kFailedGzip = 4,
+ // kDeltaCount = 5, // Deprecated.
+ kFailedDeltaReadSeed = 6,
+ kFailedDeltaApply = 7,
+ kFailedDeltaStore = 8,
+ kFailedUngzip = 9,
+ kFailedEmptyGzipContents = 10,
+ kFailedUnsupportedSeedFormat = 11,
// The following are not so much a result of the seed store, but rather
// counting the types of seeds the SeedStore() function saw. Kept in the same
// histogram for efficiency and convenience of comparing against the other
// values.
- GZIP_DELTA_COUNT,
- NON_GZIP_DELTA_COUNT,
- GZIP_FULL_COUNT,
- NON_GZIP_FULL_COUNT,
- ENUM_SIZE
+ kGzipDeltaCount = 12,
+ kNonGzipDeltaCount = 13,
+ kGzipFullCount = 14,
+ kNonGzipFullCount = 15,
+ kMaxValue = kNonGzipFullCount,
};
// The result of updating the date associated with an existing stored variations
diff --git a/chromium/components/variations/net/variations_command_line_unittest.cc b/chromium/components/variations/net/variations_command_line_unittest.cc
index 2ca4a019a86..c2fce5cc413 100644
--- a/chromium/components/variations/net/variations_command_line_unittest.cc
+++ b/chromium/components/variations/net/variations_command_line_unittest.cc
@@ -6,7 +6,6 @@
#include <stddef.h>
-#include "base/macros.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/test/scoped_feature_list.h"
diff --git a/chromium/components/variations/net/variations_http_headers.cc b/chromium/components/variations/net/variations_http_headers.cc
index 8f463333d4b..a93f5076f93 100644
--- a/chromium/components/variations/net/variations_http_headers.cc
+++ b/chromium/components/variations/net/variations_http_headers.cc
@@ -8,7 +8,7 @@
#include "base/bind.h"
#include "base/feature_list.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
@@ -256,8 +256,9 @@ class VariationsHeaderHelper {
if (variations_header_.empty())
return false;
- // Set the variations header to cors_exempt_headers rather than headers
- // to be exempted from CORS checks.
+ // Set the variations header to cors_exempt_headers rather than headers to
+ // be exempted from CORS checks, and to avoid exposing the header to service
+ // workers.
resource_request_->cors_exempt_headers.SetHeaderIfMissing(
kClientDataHeader, variations_header_);
return true;
@@ -285,7 +286,7 @@ class VariationsHeaderHelper {
GetVisibilityKey(owner, resource_request));
}
- network::ResourceRequest* resource_request_;
+ raw_ptr<network::ResourceRequest> resource_request_;
std::string variations_header_;
};
@@ -358,11 +359,6 @@ CreateSimpleURLLoaderWithVariationsHeaderUnknownSignedIn(
std::move(request), incognito, SignedIn::kNo, annotation_tag);
}
-bool IsVariationsHeader(const std::string& header_name) {
- return header_name == kClientDataHeader ||
- header_name == kOmniboxOnDeviceSuggestionsHeader;
-}
-
bool HasVariationsHeader(const network::ResourceRequest& request) {
// Note: kOmniboxOnDeviceSuggestionsHeader is not listed because this function
// is only used for testing.
diff --git a/chromium/components/variations/net/variations_http_headers.h b/chromium/components/variations/net/variations_http_headers.h
index 9b526a8ee93..33240c68305 100644
--- a/chromium/components/variations/net/variations_http_headers.h
+++ b/chromium/components/variations/net/variations_http_headers.h
@@ -116,9 +116,6 @@ CreateSimpleURLLoaderWithVariationsHeaderUnknownSignedIn(
InIncognito incognito,
const net::NetworkTrafficAnnotationTag& annotation_tag);
-// Checks if |header_name| is one for the variations header.
-bool IsVariationsHeader(const std::string& header_name);
-
// Checks if |request| contains the variations header.
bool HasVariationsHeader(const network::ResourceRequest& request);
diff --git a/chromium/components/variations/net/variations_http_headers_unittest.cc b/chromium/components/variations/net/variations_http_headers_unittest.cc
index 33808793da4..dc073e0b3d8 100644
--- a/chromium/components/variations/net/variations_http_headers_unittest.cc
+++ b/chromium/components/variations/net/variations_http_headers_unittest.cc
@@ -8,7 +8,6 @@
#include "base/containers/flat_map.h"
#include "base/cxx17_backports.h"
-#include "base/macros.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
#include "components/variations/variations.mojom.h"
diff --git a/chromium/components/variations/platform_field_trials.h b/chromium/components/variations/platform_field_trials.h
index ac96dc6e59c..a07eedb4e47 100644
--- a/chromium/components/variations/platform_field_trials.h
+++ b/chromium/components/variations/platform_field_trials.h
@@ -22,7 +22,7 @@ class COMPONENT_EXPORT(VARIATIONS) PlatformFieldTrials {
virtual ~PlatformFieldTrials() = default;
// Set up field trials for a specific platform.
- virtual void SetupFieldTrials() = 0;
+ virtual void SetUpFieldTrials() = 0;
// Create field trials that will control feature list features. This should be
// called during the same timing window as
@@ -32,7 +32,7 @@ class COMPONENT_EXPORT(VARIATIONS) PlatformFieldTrials {
// controlled by the variations seed. |low_entropy_provider| can be used as a
// parameter to creating a FieldTrial that should be visible to Google web
// properties.
- virtual void SetupFeatureControllingFieldTrials(
+ virtual void SetUpFeatureControllingFieldTrials(
bool has_seed,
const base::FieldTrial::EntropyProvider* low_entropy_provider,
base::FeatureList* feature_list) = 0;
diff --git a/chromium/components/variations/pref_names.cc b/chromium/components/variations/pref_names.cc
index 03783fa316b..201e59bff65 100644
--- a/chromium/components/variations/pref_names.cc
+++ b/chromium/components/variations/pref_names.cc
@@ -34,6 +34,9 @@ const char kVariationsFailedToFetchSeedStreak[] =
// Variations server responds with 200 or 304). This is a client timestamp.
const char kVariationsLastFetchTime[] = "variations_last_fetch_time";
+// The milestone, e.g. 96, with which the regular seed was fetched.
+const char kVariationsSeedMilestone[] = "variations_seed_milestone";
+
// Pair of <Chrome version string, country code string> representing the country
// used for filtering permanent consistency studies until the next time Chrome
// is updated.
@@ -84,6 +87,9 @@ const char kVariationsSafeSeedFetchTime[] = "variations_safe_seed_fetch_time";
// last known "safe" seed.
const char kVariationsSafeSeedLocale[] = "variations_safe_seed_locale";
+// The milestone with which the "safe" seed was fetched.
+const char kVariationsSafeSeedMilestone[] = "variations_safe_seed_milestone";
+
// A saved copy of |kVariationsPermanentConsistencyCountry|. The saved value is
// the most recent value that was successfully used by the VariationsService for
// evaluating permanent consistency studies.
diff --git a/chromium/components/variations/pref_names.h b/chromium/components/variations/pref_names.h
index a7ef1d34f1e..3d6ad20b06c 100644
--- a/chromium/components/variations/pref_names.h
+++ b/chromium/components/variations/pref_names.h
@@ -21,6 +21,7 @@ COMPONENT_EXPORT(VARIATIONS) extern const char kVariationsCrashStreak[];
COMPONENT_EXPORT(VARIATIONS)
extern const char kVariationsFailedToFetchSeedStreak[];
COMPONENT_EXPORT(VARIATIONS) extern const char kVariationsLastFetchTime[];
+COMPONENT_EXPORT(VARIATIONS) extern const char kVariationsSeedMilestone[];
COMPONENT_EXPORT(VARIATIONS)
extern const char kVariationsPermanentConsistencyCountry[];
COMPONENT_EXPORT(VARIATIONS)
@@ -32,6 +33,7 @@ COMPONENT_EXPORT(VARIATIONS) extern const char kVariationsSafeCompressedSeed[];
COMPONENT_EXPORT(VARIATIONS) extern const char kVariationsSafeSeedDate[];
COMPONENT_EXPORT(VARIATIONS) extern const char kVariationsSafeSeedFetchTime[];
COMPONENT_EXPORT(VARIATIONS) extern const char kVariationsSafeSeedLocale[];
+COMPONENT_EXPORT(VARIATIONS) extern const char kVariationsSafeSeedMilestone[];
COMPONENT_EXPORT(VARIATIONS)
extern const char kVariationsSafeSeedPermanentConsistencyCountry[];
COMPONENT_EXPORT(VARIATIONS)
diff --git a/chromium/components/variations/processed_study.h b/chromium/components/variations/processed_study.h
index 095bf2da0fd..1b60a113351 100644
--- a/chromium/components/variations/processed_study.h
+++ b/chromium/components/variations/processed_study.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/component_export.h"
+#include "base/memory/raw_ptr.h"
#include "base/metrics/field_trial.h"
namespace variations {
@@ -55,7 +56,7 @@ class COMPONENT_EXPORT(VARIATIONS) ProcessedStudy {
private:
// Corresponding Study object. Weak reference.
- const Study* study_ = nullptr;
+ raw_ptr<const Study> study_ = nullptr;
// Computed total group probability for the study.
base::FieldTrial::Probability total_probability_ = 0;
diff --git a/chromium/components/variations/service/safe_seed_manager.cc b/chromium/components/variations/service/safe_seed_manager.cc
index 641db31aff7..113a7bf1604 100644
--- a/chromium/components/variations/service/safe_seed_manager.cc
+++ b/chromium/components/variations/service/safe_seed_manager.cc
@@ -88,14 +88,15 @@ bool SafeSeedManager::ShouldRunInSafeMode() const {
void SafeSeedManager::SetActiveSeedState(
const std::string& seed_data,
const std::string& base64_seed_signature,
+ int seed_milestone,
std::unique_ptr<ClientFilterableState> client_filterable_state,
base::Time seed_fetch_time) {
DCHECK(!has_set_active_seed_state_);
has_set_active_seed_state_ = true;
active_seed_state_ = std::make_unique<ActiveSeedState>(
- seed_data, base64_seed_signature, std::move(client_filterable_state),
- seed_fetch_time);
+ seed_data, base64_seed_signature, seed_milestone,
+ std::move(client_filterable_state), seed_fetch_time);
}
void SafeSeedManager::RecordFetchStarted() {
@@ -117,6 +118,7 @@ void SafeSeedManager::RecordSuccessfulFetch(VariationsSeedStore* seed_store) {
if (active_seed_state_) {
seed_store->StoreSafeSeed(active_seed_state_->seed_data,
active_seed_state_->base64_seed_signature,
+ active_seed_state_->seed_milestone,
*active_seed_state_->client_filterable_state,
active_seed_state_->seed_fetch_time);
@@ -136,10 +138,12 @@ void SafeSeedManager::RecordSuccessfulFetch(VariationsSeedStore* seed_store) {
SafeSeedManager::ActiveSeedState::ActiveSeedState(
const std::string& seed_data,
const std::string& base64_seed_signature,
+ int seed_milestone,
std::unique_ptr<ClientFilterableState> client_filterable_state,
base::Time seed_fetch_time)
: seed_data(seed_data),
base64_seed_signature(base64_seed_signature),
+ seed_milestone(seed_milestone),
client_filterable_state(std::move(client_filterable_state)),
seed_fetch_time(seed_fetch_time) {}
diff --git a/chromium/components/variations/service/safe_seed_manager.h b/chromium/components/variations/service/safe_seed_manager.h
index 95173c17789..5c3bd660bd9 100644
--- a/chromium/components/variations/service/safe_seed_manager.h
+++ b/chromium/components/variations/service/safe_seed_manager.h
@@ -8,7 +8,7 @@
#include <memory>
#include <string>
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
class PrefRegistrySimple;
@@ -57,12 +57,13 @@ class SafeSeedManager {
virtual bool ShouldRunInSafeMode() const;
// Stores the combined server and client state that control the active
- // variations state. Must be called at most once per launch of the Chrome app.
- // As an optimization, should not be called when running in safe mode.
+ // variations state. May be called at most once per Chrome app launch. As an
+ // optimization, should not be called when running in safe mode.
// Virtual for testing.
virtual void SetActiveSeedState(
const std::string& seed_data,
const std::string& base64_seed_signature,
+ int seed_milestone,
std::unique_ptr<ClientFilterableState> client_filterable_state,
base::Time seed_fetch_time);
@@ -82,6 +83,7 @@ class SafeSeedManager {
ActiveSeedState(
const std::string& seed_data,
const std::string& base64_seed_signature,
+ int seed_milestone,
std::unique_ptr<ClientFilterableState> client_filterable_state,
base::Time seed_fetch_time);
~ActiveSeedState();
@@ -92,6 +94,9 @@ class SafeSeedManager {
// The base64-encoded signature for the seed data.
const std::string base64_seed_signature;
+ // The milestone with which the active seed was fetched.
+ const int seed_milestone;
+
// The client state which is used for filtering studies.
const std::unique_ptr<ClientFilterableState> client_filterable_state;
@@ -106,7 +111,7 @@ class SafeSeedManager {
// The pref service used to persist the variations seed. Weak reference; must
// outlive |this| instance.
- PrefService* local_state_;
+ raw_ptr<PrefService> local_state_;
};
} // namespace variations
diff --git a/chromium/components/variations/service/safe_seed_manager_unittest.cc b/chromium/components/variations/service/safe_seed_manager_unittest.cc
index 94ecf9a419f..1aa1c327306 100644
--- a/chromium/components/variations/service/safe_seed_manager_unittest.cc
+++ b/chromium/components/variations/service/safe_seed_manager_unittest.cc
@@ -9,7 +9,6 @@
#include "base/base_switches.h"
#include "base/command_line.h"
-#include "base/macros.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/time/time.h"
#include "components/metrics/clean_exit_beacon.h"
@@ -25,6 +24,7 @@ namespace {
const char kTestSeed[] = "compressed, base-64 encoded serialized seed data";
const char kTestSignature[] = "a completely unforged signature, I promise!";
+const int kTestSeedMilestone = 92;
const char kTestLocale[] = "en-US";
const char kTestPermanentConsistencyCountry[] = "US";
const char kTestSessionConsistencyCountry[] = "CA";
@@ -36,8 +36,10 @@ base::Time GetTestFetchTime() {
// A simple fake data store.
class FakeSeedStore : public VariationsSeedStore {
public:
- explicit FakeSeedStore(PrefService* local_state)
- : VariationsSeedStore(local_state) {}
+ explicit FakeSeedStore(TestingPrefServiceSimple* local_state)
+ : VariationsSeedStore(local_state) {
+ VariationsSeedStore::RegisterPrefs(local_state->registry());
+ }
FakeSeedStore(const FakeSeedStore&) = delete;
FakeSeedStore& operator=(const FakeSeedStore&) = delete;
@@ -46,10 +48,12 @@ class FakeSeedStore : public VariationsSeedStore {
bool StoreSafeSeed(const std::string& seed_data,
const std::string& base64_seed_signature,
+ int seed_milestone,
const ClientFilterableState& client_state,
base::Time seed_fetch_time) override {
seed_data_ = seed_data;
signature_ = base64_seed_signature;
+ seed_milestone_ = seed_milestone;
date_ = client_state.reference_date;
locale_ = client_state.locale;
permanent_consistency_country_ = client_state.permanent_consistency_country;
@@ -60,6 +64,7 @@ class FakeSeedStore : public VariationsSeedStore {
const std::string& seed_data() const { return seed_data_; }
const std::string& signature() const { return signature_; }
+ int seed_milestone() const { return seed_milestone_; }
const base::Time& date() const { return date_; }
const std::string& locale() const { return locale_; }
const std::string& permanent_consistency_country() const {
@@ -74,6 +79,7 @@ class FakeSeedStore : public VariationsSeedStore {
// The stored data.
std::string seed_data_;
std::string signature_;
+ int seed_milestone_ = 0;
base::Time date_;
std::string locale_;
std::string permanent_consistency_country_;
@@ -81,9 +87,10 @@ class FakeSeedStore : public VariationsSeedStore {
base::Time fetch_time_;
};
-// Passes the default test values as the active state into the
-// |safe_seed_manager|.
-void SetDefaultActiveState(SafeSeedManager* safe_seed_manager) {
+// Passes the default test values as the active state into |safe_seed_manager|
+// and |local_state|.
+void SetDefaultActiveState(SafeSeedManager* safe_seed_manager,
+ PrefService* local_state) {
std::unique_ptr<ClientFilterableState> client_state =
std::make_unique<ClientFilterableState>(
base::BindOnce([] { return false; }));
@@ -93,14 +100,18 @@ void SetDefaultActiveState(SafeSeedManager* safe_seed_manager) {
client_state->session_consistency_country = kTestSessionConsistencyCountry;
client_state->reference_date = base::Time::UnixEpoch();
+ local_state->SetInteger(prefs::kVariationsSeedMilestone, kTestSeedMilestone);
+
safe_seed_manager->SetActiveSeedState(
- kTestSeed, kTestSignature, std::move(client_state), GetTestFetchTime());
+ kTestSeed, kTestSignature, kTestSeedMilestone, std::move(client_state),
+ GetTestFetchTime());
}
// Verifies that the default test values were written to the seed store.
void ExpectDefaultActiveState(const FakeSeedStore& seed_store) {
EXPECT_EQ(kTestSeed, seed_store.seed_data());
EXPECT_EQ(kTestSignature, seed_store.signature());
+ EXPECT_EQ(kTestSeedMilestone, seed_store.seed_milestone());
EXPECT_EQ(kTestLocale, seed_store.locale());
EXPECT_EQ(kTestPermanentConsistencyCountry,
seed_store.permanent_consistency_country());
@@ -126,36 +137,34 @@ class SafeSeedManagerTest : public testing::Test {
TEST_F(SafeSeedManagerTest, RecordSuccessfulFetch_FirstCallSavesSafeSeed) {
SafeSeedManager safe_seed_manager(&prefs_);
- SetDefaultActiveState(&safe_seed_manager);
-
FakeSeedStore seed_store(&prefs_);
- safe_seed_manager.RecordSuccessfulFetch(&seed_store);
+ SetDefaultActiveState(&safe_seed_manager, &prefs_);
+ safe_seed_manager.RecordSuccessfulFetch(&seed_store);
ExpectDefaultActiveState(seed_store);
}
TEST_F(SafeSeedManagerTest, RecordSuccessfulFetch_RepeatedCallsRetainSafeSeed) {
SafeSeedManager safe_seed_manager(&prefs_);
- SetDefaultActiveState(&safe_seed_manager);
-
FakeSeedStore seed_store(&prefs_);
+ SetDefaultActiveState(&safe_seed_manager, &prefs_);
+
safe_seed_manager.RecordSuccessfulFetch(&seed_store);
safe_seed_manager.RecordSuccessfulFetch(&seed_store);
safe_seed_manager.RecordSuccessfulFetch(&seed_store);
-
ExpectDefaultActiveState(seed_store);
}
TEST_F(SafeSeedManagerTest,
RecordSuccessfulFetch_NoActiveState_DoesntSaveSafeSeed) {
SafeSeedManager safe_seed_manager(&prefs_);
+ FakeSeedStore seed_store(&prefs_);
// Omit setting any active state.
- FakeSeedStore seed_store(&prefs_);
safe_seed_manager.RecordSuccessfulFetch(&seed_store);
-
EXPECT_EQ(std::string(), seed_store.seed_data());
EXPECT_EQ(std::string(), seed_store.signature());
+ EXPECT_EQ(0, seed_store.seed_milestone());
EXPECT_EQ(std::string(), seed_store.locale());
EXPECT_EQ(std::string(), seed_store.permanent_consistency_country());
EXPECT_EQ(std::string(), seed_store.session_consistency_country());
diff --git a/chromium/components/variations/service/ui_string_overrider.h b/chromium/components/variations/service/ui_string_overrider.h
index c02cc59c405..a1cda9c7471 100644
--- a/chromium/components/variations/service/ui_string_overrider.h
+++ b/chromium/components/variations/service/ui_string_overrider.h
@@ -8,8 +8,6 @@
#include <stddef.h>
#include <stdint.h>
-#include "base/macros.h"
-
namespace variations {
// Provides a mapping from hashes of generated resource names to their IDs. The
diff --git a/chromium/components/variations/service/ui_string_overrider_unittest.cc b/chromium/components/variations/service/ui_string_overrider_unittest.cc
index 1ea2539a077..f8b6bc437c6 100644
--- a/chromium/components/variations/service/ui_string_overrider_unittest.cc
+++ b/chromium/components/variations/service/ui_string_overrider_unittest.cc
@@ -7,7 +7,6 @@
#include <stddef.h>
#include <stdint.h>
-#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace variations {
diff --git a/chromium/components/variations/service/variations_field_trial_creator.cc b/chromium/components/variations/service/variations_field_trial_creator.cc
index 30d8b8a0d9b..86461fd574c 100644
--- a/chromium/components/variations/service/variations_field_trial_creator.cc
+++ b/chromium/components/variations/service/variations_field_trial_creator.cc
@@ -41,6 +41,7 @@
#include "components/variations/variations_seed_processor.h"
#include "components/variations/variations_switches.h"
#include "components/version_info/channel.h"
+#include "components/version_info/version_info.h"
#include "ui/base/device_form_factor.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
@@ -173,7 +174,7 @@ std::string VariationsFieldTrialCreator::GetLatestCountry() const {
: local_state()->GetString(prefs::kVariationsCountry);
}
-bool VariationsFieldTrialCreator::SetupFieldTrials(
+bool VariationsFieldTrialCreator::SetUpFieldTrials(
const std::vector<std::string>& variation_ids,
const std::vector<base::FeatureList::FeatureOverrideInfo>& extra_overrides,
std::unique_ptr<const base::FieldTrial::EntropyProvider>
@@ -189,36 +190,6 @@ bool VariationsFieldTrialCreator::SetupFieldTrials(
DCHECK(platform_field_trials);
DCHECK(safe_seed_manager);
- const base::CommandLine* command_line =
- base::CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kForceFieldTrialParams)) {
- bool result = AssociateParamsFromString(
- command_line->GetSwitchValueASCII(switches::kForceFieldTrialParams));
- if (!result) {
- // Some field trial params implement things like csv or json with a
- // particular param. If some control characters are not %-encoded, it can
- // lead to confusing error messages, so add a hint here.
- ExitWithMessage(base::StringPrintf(
- "Invalid --%s list specified. Make sure you %%-"
- "encode the following characters in param values: %%:/.,",
- switches::kForceFieldTrialParams));
- }
- }
-
- // Ensure any field trials specified on the command line are initialized.
- if (command_line->HasSwitch(::switches::kForceFieldTrials)) {
- // Create field trials without activating them, so that this behaves in a
- // consistent manner with field trials created from the server.
- bool result = base::FieldTrialList::CreateTrialsFromString(
- command_line->GetSwitchValueASCII(::switches::kForceFieldTrials));
- if (!result) {
- ExitWithMessage(base::StringPrintf("Invalid --%s list specified.",
- ::switches::kForceFieldTrials));
- }
- }
-
-#if !defined(OS_ANDROID)
- // TODO(crbug/1248239): Enable Extended Variations Safe Mode on Android.
if (extend_variations_safe_mode &&
!metrics_state_manager->is_background_session()) {
// If the session is expected to be a background session, then do not extend
@@ -228,11 +199,15 @@ bool VariationsFieldTrialCreator::SetupFieldTrials(
// crashes.
MaybeExtendVariationsSafeMode(metrics_state_manager);
}
-#endif
+ // TODO(crbug/1257204): Some FieldTrial-setup-related code is here and some is
+ // in MetricsStateManager::InstantiateFieldTrialList(). It's not ideal that
+ // it's in two places.
VariationsIdsProvider* http_header_provider =
VariationsIdsProvider::GetInstance();
http_header_provider->SetLowEntropySourceValue(low_entropy_source_value);
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
// Force the variation ids selected in chrome://flags and/or specified using
// the command-line flag.
auto result = http_header_provider->ForceVariationIds(
@@ -291,7 +266,7 @@ bool VariationsFieldTrialCreator::SetupFieldTrials(
feature_list.get(), safe_seed_manager);
}
- platform_field_trials->SetupFeatureControllingFieldTrials(
+ platform_field_trials->SetUpFeatureControllingFieldTrials(
used_seed, low_entropy_provider.get(), feature_list.get());
base::FeatureList::SetInstance(std::move(feature_list));
@@ -305,7 +280,7 @@ bool VariationsFieldTrialCreator::SetupFieldTrials(
}
// This must be called after |local_state_| is initialized.
- platform_field_trials->SetupFieldTrials();
+ platform_field_trials->SetUpFieldTrials();
return used_seed;
}
@@ -370,24 +345,25 @@ std::string VariationsFieldTrialCreator::LoadPermanentConsistencyCountry(
const base::ListValue* list_value =
local_state()->GetList(prefs::kVariationsPermanentConsistencyCountry);
- std::string stored_version_string;
- std::string stored_country;
+ const std::string* stored_version_string = nullptr;
+ const std::string* stored_country = nullptr;
// Determine if the saved pref value is present and valid.
const bool is_pref_empty = list_value->GetList().empty();
- const bool is_pref_valid = list_value->GetList().size() == 2 &&
- list_value->GetString(0, &stored_version_string) &&
- list_value->GetString(1, &stored_country) &&
- base::Version(stored_version_string).IsValid();
+ const bool is_pref_valid =
+ list_value->GetList().size() == 2 &&
+ (stored_version_string = list_value->GetList()[0].GetIfString()) &&
+ (stored_country = list_value->GetList()[1].GetIfString()) &&
+ base::Version(*stored_version_string).IsValid();
// Determine if the version from the saved pref matches |version|.
const bool does_version_match =
- is_pref_valid && version == base::Version(stored_version_string);
+ is_pref_valid && version == base::Version(*stored_version_string);
// Determine if the country in the saved pref matches the country in
// |latest_country|.
const bool does_country_match = is_pref_valid && !latest_country.empty() &&
- stored_country == latest_country;
+ *stored_country == latest_country;
// Record a histogram for how the saved pref value compares to the current
// version and the country code in the variations seed.
@@ -414,7 +390,7 @@ std::string VariationsFieldTrialCreator::LoadPermanentConsistencyCountry(
// Use the stored country if one is available and was fetched since the last
// time Chrome was updated.
if (does_version_match)
- return stored_country;
+ return *stored_country;
if (latest_country.empty()) {
if (!is_pref_valid)
@@ -469,6 +445,27 @@ bool VariationsFieldTrialCreator::IsOverrideResourceMapEmpty() {
return overridden_strings_map_.empty();
}
+void VariationsFieldTrialCreator::MaybeExtendVariationsSafeMode(
+ metrics::MetricsStateManager* metrics_state_manager) {
+ const std::string group_name =
+ base::FieldTrialList::FindFullName(kExtendedSafeModeTrial);
+ if (group_name.empty() || group_name == kDefaultGroup)
+ return;
+
+ if (group_name == kControlGroup) {
+ // Populate the histogram for the control group to more easily compare it
+ // with the groups that introduce new behavior.
+ SCOPED_UMA_HISTOGRAM_TIMER_MICROS(
+ "Variations.ExtendedSafeMode.WritePrefsTime");
+ return;
+ }
+
+ DCHECK_EQ(group_name, kSignalAndWriteViaFileUtilGroup);
+ metrics_state_manager->LogHasSessionShutdownCleanly(
+ /*has_session_shutdown_cleanly=*/false,
+ /*write_synchronously=*/true);
+}
+
bool VariationsFieldTrialCreator::HasSeedExpired(bool is_safe_seed) {
const base::Time fetch_time = is_safe_seed
? GetSeedStore()->GetSafeSeedFetchTime()
@@ -499,6 +496,21 @@ bool VariationsFieldTrialCreator::HasSeedExpired(bool is_safe_seed) {
return has_seed_expired;
}
+bool VariationsFieldTrialCreator::IsSeedForFutureMilestone(bool is_safe_seed) {
+ const std::string milestone_pref = is_safe_seed
+ ? prefs::kVariationsSafeSeedMilestone
+ : prefs::kVariationsSeedMilestone;
+
+ // The regular and safe seed milestone prefs were added in M97, so the prefs
+ // are not populated for seeds stored before then.
+ int seed_milestone = local_state()->GetInteger(milestone_pref);
+ if (!seed_milestone)
+ return false;
+
+ int client_milestone = version_info::GetMajorVersionNumberAsInt();
+ return seed_milestone > client_milestone;
+}
+
bool VariationsFieldTrialCreator::CreateTrialsFromSeed(
const base::FieldTrial::EntropyProvider* low_entropy_provider,
base::FeatureList* feature_list,
@@ -528,10 +540,17 @@ bool VariationsFieldTrialCreator::CreateTrialsFromSeed(
LoadSeedResult result =
GetSeedStore()->LoadSafeSeed(&seed, client_filterable_state.get());
if (result == LoadSeedResult::kSuccess) {
+ // TODO(crbug/1261685): The expiry and milestone checks are repeated below
+ // for regular seeds. Refactor this.
if (HasSeedExpired(/*is_safe_seed=*/true)) {
RecordVariationsSeedUsage(SeedUsage::kExpiredSafeSeedNotUsed);
return false;
}
+ if (IsSeedForFutureMilestone(/*is_safe_seed=*/true)) {
+ RecordVariationsSeedUsage(
+ SeedUsage::kSafeSeedForFutureMilestoneNotUsed);
+ return false;
+ }
RecordVariationsSeedUsage(SeedUsage::kSafeSeedUsed);
run_in_safe_mode = true; // This line is a no-op. Added for clarity.
} else if (result == LoadSeedResult::kEmpty) {
@@ -559,6 +578,11 @@ bool VariationsFieldTrialCreator::CreateTrialsFromSeed(
RecordVariationsSeedUsage(seed_usage);
return false;
}
+ if (IsSeedForFutureMilestone(/*is_safe_seed=*/false)) {
+ RecordVariationsSeedUsage(
+ SeedUsage::kRegularSeedForFutureMilestoneNotUsed);
+ return false;
+ }
seed_usage = should_run_in_safe_mode
? SeedUsage::kRegularSeedUsedAfterEmptySafeSeedLoaded
: SeedUsage::kRegularSeedUsed;
@@ -589,13 +613,15 @@ bool VariationsFieldTrialCreator::CreateTrialsFromSeed(
// running in safe mode – once running in safe mode, there can never be a need
// to save the active state to the safe seed prefs.
if (!run_in_safe_mode) {
- safe_seed_manager->SetActiveSeedState(seed_data, base64_seed_signature,
- std::move(client_filterable_state),
- seed_store_->GetLastFetchTime());
+ safe_seed_manager->SetActiveSeedState(
+ seed_data, base64_seed_signature,
+ local_state()->GetInteger(prefs::kVariationsSeedMilestone),
+ std::move(client_filterable_state), seed_store_->GetLastFetchTime());
}
- UMA_HISTOGRAM_TIMES("Variations.SeedProcessingTime",
- base::TimeTicks::Now() - start_time);
+ base::UmaHistogramCounts1M("Variations.AppliedSeed.Size", seed_data.size());
+ base::UmaHistogramTimes("Variations.SeedProcessingTime",
+ base::TimeTicks::Now() - start_time);
return true;
}
@@ -630,43 +656,4 @@ Study::Platform VariationsFieldTrialCreator::GetPlatform() {
return ClientFilterableState::GetCurrentPlatform();
}
-#if !defined(OS_ANDROID)
-void VariationsFieldTrialCreator::MaybeExtendVariationsSafeMode(
- metrics::MetricsStateManager* metrics_state_manager) const {
- version_info::Channel channel = client_->GetChannelForVariations();
- if (channel != version_info::Channel::UNKNOWN &&
- channel != version_info::Channel::CANARY &&
- channel != version_info::Channel::DEV) {
- return;
- }
-
- int default_group;
- scoped_refptr<base::FieldTrial> trial(
- base::FieldTrialList::FactoryGetFieldTrial(
- kExtendedSafeModeTrial, 100, kDefaultGroup,
- base::FieldTrial::ONE_TIME_RANDOMIZED, &default_group));
-
- const int control_group = trial->AppendGroup(kControlGroup, 25);
- const int write_only_group =
- trial->AppendGroup(kWriteSynchronouslyViaPrefServiceGroup, 25);
- trial->AppendGroup(kSignalAndWriteSynchronouslyViaPrefServiceGroup, 25);
- trial->AppendGroup(kSignalAndWriteViaFileUtilGroup, 25);
- const int assigned_group = trial->group();
-
- if (assigned_group == control_group)
- return;
-
- // For clients in the SignalAndWrite* groups, the beacon is updated and a
- // synchronous write is performed. Conversely, for clients in
- // |write_only_group|, i.e. the WriteSynchronouslyViaPrefService group, prefs
- // are written synchronously without updating the beacon, i.e. without
- // signaling that Chrome should start watching for crashes.
- bool update_beacon = assigned_group != write_only_group;
-
- metrics_state_manager->LogHasSessionShutdownCleanly(
- /*has_session_shutdown_cleanly=*/false, /*write_synchronously=*/true,
- update_beacon);
-}
-#endif // !defined(OS_ANDROID)
-
} // namespace variations
diff --git a/chromium/components/variations/service/variations_field_trial_creator.h b/chromium/components/variations/service/variations_field_trial_creator.h
index 463fac1acaf..8baf0c6500b 100644
--- a/chromium/components/variations/service/variations_field_trial_creator.h
+++ b/chromium/components/variations/service/variations_field_trial_creator.h
@@ -11,7 +11,7 @@
#include <vector>
#include "base/compiler_specific.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -44,7 +44,9 @@ enum class SeedUsage {
kRegularSeedUsedAfterEmptySafeSeedLoaded = 6,
kExpiredRegularSeedNotUsedAfterEmptySafeSeedLoaded = 7,
kCorruptedRegularSeedNotUsedAfterEmptySafeSeedLoaded = 8,
- kMaxValue = kCorruptedRegularSeedNotUsedAfterEmptySafeSeedLoaded,
+ kRegularSeedForFutureMilestoneNotUsed = 9,
+ kSafeSeedForFutureMilestoneNotUsed = 10,
+ kMaxValue = kSafeSeedForFutureMilestoneNotUsed,
};
// Denotes a variations seed's expiry state. Exposed for testing.
@@ -77,7 +79,7 @@ class PlatformFieldTrials;
class SafeSeedManager;
class VariationsServiceClient;
-// Used to setup field trials based on stored variations seed data.
+// Used to set up field trials based on stored variations seed data.
class VariationsFieldTrialCreator {
public:
// Caller is responsible for ensuring that objects passed to the constructor
@@ -128,7 +130,7 @@ class VariationsFieldTrialCreator {
// explicit --disable-features and --enable-features from the command line
// take precedence over |extra_overrides|, which takes precedence over the
// field trials.
- bool SetupFieldTrials(
+ bool SetUpFieldTrials(
const std::vector<std::string>& variation_ids,
const std::vector<base::FeatureList::FeatureOverrideInfo>&
extra_overrides,
@@ -176,6 +178,14 @@ class VariationsFieldTrialCreator {
// Returns the locale that was used for evaluating trials.
const std::string& application_locale() const { return application_locale_; }
+ protected:
+ // If the client is in an Extended Variations Safe Mode experiment group,
+ // applies group-specific behavior. Does nothing if the client is not in the
+ // experiment. See CleanExitBeacon::Initialize() for group assignment details.
+ // Protected and virtual for testing.
+ virtual void MaybeExtendVariationsSafeMode(
+ metrics::MetricsStateManager* metrics_state_manager);
+
private:
// Returns true if the loaded VariationsSeed has expired. An expired seed is
// one that (a) was fetched over |kMaxVariationsSeedAgeDays| ago and (b) is
@@ -184,6 +194,12 @@ class VariationsFieldTrialCreator {
// Also, records a couple VariationsSeed-related metrics.
bool HasSeedExpired(bool is_safe_seed);
+ // Returns true if the loaded VariationsSeed is for a future milestone (e.g.
+ // if the client is on M92 and the seed was fetched with M93). A seed for a
+ // future milestone is invalid as it may be missing studies filtered out by
+ // the server.
+ bool IsSeedForFutureMilestone(bool is_safe_seed);
+
// Creates field trials based on the variations seed loaded from local state.
// If there is a problem loading the seed data, all trials specified by the
// seed may not be created. Some field trials are configured to override or
@@ -209,18 +225,10 @@ class VariationsFieldTrialCreator {
// Get the platform we're running on, respecting OverrideVariationsPlatform().
Study::Platform GetPlatform();
-#if !defined(OS_ANDROID)
- // On channels that support the ExtendedVariationsSafeMode experiment, (a)
- // assigns the client to an experiment group and (b) applies group-specific
- // behavior. Does nothing if the channel does not support the experiment.
- void MaybeExtendVariationsSafeMode(
- metrics::MetricsStateManager* metrics_state_manager) const;
-#endif
-
PrefService* local_state() { return seed_store_->local_state(); }
const PrefService* local_state() const { return seed_store_->local_state(); }
- VariationsServiceClient* client_;
+ raw_ptr<VariationsServiceClient> client_;
UIStringOverrider ui_string_overrider_;
diff --git a/chromium/components/variations/service/variations_field_trial_creator_unittest.cc b/chromium/components/variations/service/variations_field_trial_creator_unittest.cc
index 6c73d8563c0..4daa6a05659 100644
--- a/chromium/components/variations/service/variations_field_trial_creator_unittest.cc
+++ b/chromium/components/variations/service/variations_field_trial_creator_unittest.cc
@@ -5,17 +5,17 @@
#include "components/variations/service/variations_field_trial_creator.h"
#include <stddef.h>
+#include <cstring>
#include <memory>
#include <utility>
#include "base/callback.h"
#include "base/callback_helpers.h"
-#include "base/containers/contains.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_entropy_provider.h"
#include "base/test/scoped_field_trial_list_resetter.h"
@@ -23,7 +23,6 @@
#include "base/time/time.h"
#include "base/version.h"
#include "build/build_config.h"
-#include "components/metrics/clean_exit_beacon.h"
#include "components/metrics/client_info.h"
#include "components/metrics/metrics_service.h"
#include "components/metrics/metrics_state_manager.h"
@@ -40,7 +39,6 @@
#include "components/variations/service/variations_service.h"
#include "components/variations/service/variations_service_client.h"
#include "components/variations/variations_seed_store.h"
-#include "components/variations/variations_switches.h"
#include "components/variations/variations_test_utils.h"
#include "components/version_info/channel.h"
#include "components/version_info/version_info.h"
@@ -50,7 +48,7 @@
#if defined(OS_ANDROID)
#include "components/variations/seed_response.h"
-#endif // OS_ANDROID
+#endif
namespace variations {
namespace {
@@ -70,11 +68,10 @@ const char kTestSeedSerialNumber[] = "123";
// Constants used to mock the serialized seed state.
const char kTestSeedSerializedData[] = "a serialized seed, 100% realistic";
const char kTestSeedSignature[] = "a totally valid signature, I swear!";
+const int kTestSeedMilestone = 90;
-#if !defined(OS_ANDROID)
// The content of an empty prefs file.
const char kEmptyPrefsFile[] = "{}";
-#endif // !defined(OS_ANDROID)
// Used for similar tests.
struct TestParams {
@@ -83,8 +80,8 @@ struct TestParams {
const base::Time binary_build_time;
};
-// Populates |seed| with simple test data. The resulting seed will contain one
-// study called "test", which contains one experiment called "abc" with
+// Returns a seed with simple test data. The seed has a single study,
+// "UMA-Uniformity-Trial-10-Percent", which has a single experiment, "abc", with
// probability weight 100.
VariationsSeed CreateTestSeed() {
VariationsSeed seed;
@@ -98,11 +95,12 @@ VariationsSeed CreateTestSeed() {
return seed;
}
-// Returns a seed containing simple test data. The resulting seed will contain
-// one study called "test", which contains one experiment called "abc.safe" with
-// probability weight 100. This is intended to be used whenever a "safe" seed is
-// called for, so that test expectations can distinguish between a "safe" seed
-// and a "latest" seed.
+// Returns a seed with simple test data. The seed has a single study,
+// "UMA-Uniformity-Trial-10-Percent", which has a single experiment,
+// "abc.safe", with probability weight 100.
+//
+// Intended to be used when a "safe" seed is needed so that test expectations
+// can distinguish between a regular and safe seeds.
VariationsSeed CreateTestSafeSeed() {
VariationsSeed seed = CreateTestSeed();
Study* study = seed.mutable_study(0);
@@ -133,7 +131,7 @@ std::string SerializeSeed(const VariationsSeed& seed) {
seed.SerializeToString(&serialized_seed);
return serialized_seed;
}
-#endif // OS_ANDROID
+#endif // defined(OS_ANDROID)
class TestPlatformFieldTrials : public PlatformFieldTrials {
public:
@@ -145,8 +143,8 @@ class TestPlatformFieldTrials : public PlatformFieldTrials {
~TestPlatformFieldTrials() override = default;
// PlatformFieldTrials:
- void SetupFieldTrials() override {}
- void SetupFeatureControllingFieldTrials(
+ void SetUpFieldTrials() override {}
+ void SetUpFeatureControllingFieldTrials(
bool has_seed,
const base::FieldTrial::EntropyProvider* low_entropy_provider,
base::FeatureList* feature_list) override {}
@@ -163,18 +161,20 @@ class MockSafeSeedManager : public SafeSeedManager {
~MockSafeSeedManager() override = default;
MOCK_CONST_METHOD0(ShouldRunInSafeMode, bool());
- MOCK_METHOD4(DoSetActiveSeedState,
+ MOCK_METHOD5(DoSetActiveSeedState,
void(const std::string& seed_data,
const std::string& base64_seed_signature,
+ int seed_milestone,
ClientFilterableState* client_filterable_state,
base::Time seed_fetch_time));
void SetActiveSeedState(
const std::string& seed_data,
const std::string& base64_seed_signature,
+ int seed_milestone,
std::unique_ptr<ClientFilterableState> client_filterable_state,
base::Time seed_fetch_time) override {
- DoSetActiveSeedState(seed_data, base64_seed_signature,
+ DoSetActiveSeedState(seed_data, base64_seed_signature, seed_milestone,
client_filterable_state.get(), seed_fetch_time);
}
};
@@ -210,10 +210,7 @@ class TestVariationsServiceClient : public VariationsServiceClient {
private:
// VariationsServiceClient:
version_info::Channel GetChannel() override {
- // Set to stable to skip logic related to the Extended Variations Safe Mode
- // experiment.
- // TODO(crbug/1241702): Clean this up once the experiment is done.
- return version_info::Channel::STABLE;
+ return version_info::Channel::UNKNOWN;
}
std::string restrict_parameter_;
@@ -277,6 +274,7 @@ class TestVariationsFieldTrialCreator : public VariationsFieldTrialCreator {
PrefService* local_state,
TestVariationsServiceClient* client,
SafeSeedManager* safe_seed_manager,
+ version_info::Channel channel = version_info::Channel::UNKNOWN,
const base::FilePath user_data_dir = base::FilePath(),
metrics::StartupVisibility startup_visibility =
metrics::StartupVisibility::kUnknown)
@@ -290,7 +288,7 @@ class TestVariationsFieldTrialCreator : public VariationsFieldTrialCreator {
build_time_(base::Time::Now()) {
metrics_state_manager_ = metrics::MetricsStateManager::Create(
local_state, &enabled_state_provider_, std::wstring(), user_data_dir,
- startup_visibility);
+ startup_visibility, channel);
metrics_state_manager_->InstantiateFieldTrialList();
}
@@ -301,11 +299,11 @@ class TestVariationsFieldTrialCreator : public VariationsFieldTrialCreator {
~TestVariationsFieldTrialCreator() override = default;
- // A convenience wrapper around SetupFieldTrials() which passes default values
+ // A convenience wrapper around SetUpFieldTrials() which passes default values
// for uninteresting params.
- bool SetupFieldTrials(bool extend_variations_safe_mode = true) {
+ bool SetUpFieldTrials(bool extend_variations_safe_mode = true) {
TestPlatformFieldTrials platform_field_trials;
- return VariationsFieldTrialCreator::SetupFieldTrials(
+ return VariationsFieldTrialCreator::SetUpFieldTrials(
/*variation_ids=*/std::vector<std::string>(),
std::vector<base::FeatureList::FeatureOverrideInfo>(),
/*low_entropy_provider=*/nullptr, std::make_unique<base::FeatureList>(),
@@ -316,6 +314,17 @@ class TestVariationsFieldTrialCreator : public VariationsFieldTrialCreator {
TestVariationsSeedStore* seed_store() { return &seed_store_; }
void SetBuildTime(const base::Time& time) { build_time_ = time; }
+ bool was_maybe_extend_variations_safe_mode_called() {
+ return was_maybe_extend_variations_safe_mode_called_;
+ }
+
+ protected:
+ void MaybeExtendVariationsSafeMode(
+ metrics::MetricsStateManager* metrics_state_manager) override {
+ was_maybe_extend_variations_safe_mode_called_ = true;
+ VariationsFieldTrialCreator::MaybeExtendVariationsSafeMode(
+ metrics_state_manager);
+ }
private:
VariationsSeedStore* GetSeedStore() override { return &seed_store_; }
@@ -323,9 +332,10 @@ class TestVariationsFieldTrialCreator : public VariationsFieldTrialCreator {
metrics::TestEnabledStateProvider enabled_state_provider_;
TestVariationsSeedStore seed_store_;
- SafeSeedManager* const safe_seed_manager_;
+ const raw_ptr<SafeSeedManager> safe_seed_manager_;
base::Time build_time_;
std::unique_ptr<metrics::MetricsStateManager> metrics_state_manager_;
+ bool was_maybe_extend_variations_safe_mode_called_ = false;
};
} // namespace
@@ -366,8 +376,6 @@ class FieldTrialCreatorTest : public ::testing::Test {
std::unique_ptr<base::FeatureList> global_feature_list_;
};
-#if !defined(OS_ANDROID)
-// TODO(crbug/1248239): Enable Extended Variations Safe Mode on Android.
class FieldTrialCreatorSafeModeExperimentTest : public FieldTrialCreatorTest {
public:
FieldTrialCreatorSafeModeExperimentTest()
@@ -399,26 +407,6 @@ class FieldTrialCreatorSafeModeExperimentTest : public FieldTrialCreatorTest {
return pref_service_factory.Create(pref_registry);
}
- // Sets up the extended safe mode experiment such that |group_name| is the
- // active group. Returns the numeric value that denotes the active group.
- int SetUpExtendedSafeModeExperiment(const std::string& group_name) {
- int default_group;
- scoped_refptr<base::FieldTrial> trial(
- base::FieldTrialList::FactoryGetFieldTrial(
- kExtendedSafeModeTrial, 100, kDefaultGroup,
- base::FieldTrial::ONE_TIME_RANDOMIZED, &default_group));
-
- int active_group;
- if (group_name == kDefaultGroup) {
- active_group = default_group;
- } else {
- active_group = trial->AppendGroup(group_name, 100);
- }
-
- trial->SetForced();
- return active_group;
- }
-
const base::FilePath prefs_file() const { return prefs_file_; }
const base::FilePath user_data_dir_path() const {
return temp_dir_.GetPath();
@@ -435,16 +423,15 @@ class FieldTrialCreatorSafeModeExperimentTest : public FieldTrialCreatorTest {
struct StartupVisibilityTestParams {
const std::string test_name;
metrics::StartupVisibility startup_visibility;
- bool is_trial_active;
+ bool extend_safe_mode;
};
class FieldTrialCreatorTestWithStartupVisibility
: public FieldTrialCreatorSafeModeExperimentTest,
public ::testing::WithParamInterface<StartupVisibilityTestParams> {};
-#endif // !defined(OS_ANDROID)
// Verify that unexpired seeds are used.
-TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ValidSeed_NotExpired) {
+TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_ValidSeed_NotExpired) {
DisableTestingConfig();
const base::Time now = base::Time::Now();
@@ -463,9 +450,10 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ValidSeed_NotExpired) {
NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
ON_CALL(safe_seed_manager, ShouldRunInSafeMode())
.WillByDefault(Return(false));
- EXPECT_CALL(safe_seed_manager,
- DoSetActiveSeedState(kTestSeedSerializedData,
- kTestSeedSignature, _, seed_fetch_time))
+ EXPECT_CALL(
+ safe_seed_manager,
+ DoSetActiveSeedState(kTestSeedSerializedData, kTestSeedSignature,
+ kTestSeedMilestone, _, seed_fetch_time))
.Times(1);
TestVariationsServiceClient variations_service_client;
@@ -476,11 +464,14 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ValidSeed_NotExpired) {
// Simulate the seed being stored.
prefs_.SetTime(prefs::kVariationsLastFetchTime, seed_fetch_time);
+ // Simulate a seed from an earlier (i.e. valid) milestone.
+ prefs_.SetInteger(prefs::kVariationsSeedMilestone, kTestSeedMilestone);
+
// Check that field trials are created from the seed. Since the test study
// has only one experiment with 100% probability weight, we must be part of
// it.
base::HistogramTester histogram_tester;
- EXPECT_TRUE(field_trial_creator.SetupFieldTrials());
+ EXPECT_TRUE(field_trial_creator.SetUpFieldTrials());
EXPECT_EQ(kTestSeedExperimentName,
base::FieldTrialList::FindFullName(kTestSeedStudyName));
@@ -492,12 +483,14 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ValidSeed_NotExpired) {
freshness_in_minutes, 1);
histogram_tester.ExpectUniqueSample("Variations.SeedUsage",
SeedUsage::kRegularSeedUsed, 1);
+ histogram_tester.ExpectUniqueSample("Variations.AppliedSeed.Size",
+ strlen(kTestSeedSerializedData), 1);
ResetFeatureList();
}
}
-TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ValidSeed_NoLastFetchTime) {
+TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_ValidSeed_NoLastFetchTime) {
DisableTestingConfig();
// With a valid seed on first run, the safe seed manager should be informed of
@@ -509,7 +502,7 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ValidSeed_NoLastFetchTime) {
const base::Time start_time = base::Time::Now();
EXPECT_CALL(safe_seed_manager,
DoSetActiveSeedState(kTestSeedSerializedData, kTestSeedSignature,
- _, Ge(start_time)))
+ _, _, Ge(start_time)))
.Times(1);
TestVariationsServiceClient variations_service_client;
@@ -522,7 +515,7 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ValidSeed_NoLastFetchTime) {
// Check that field trials are created from the seed. Since the test study has
// only one experiment with 100% probability weight, we must be part of it.
base::HistogramTester histogram_tester;
- EXPECT_TRUE(field_trial_creator.SetupFieldTrials());
+ EXPECT_TRUE(field_trial_creator.SetUpFieldTrials());
EXPECT_EQ(base::FieldTrialList::FindFullName(kTestSeedStudyName),
kTestSeedExperimentName);
@@ -536,7 +529,51 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ValidSeed_NoLastFetchTime) {
SeedUsage::kRegularSeedUsed, 1);
}
-TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ExpiredSeed) {
+// Verify that a regular seed can be used when the milestone with which the seed
+// was fetched is unknown. This can happen if the seed was fetched before the
+// milestone pref was added.
+TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_ValidSeed_NoMilestone) {
+ DisableTestingConfig();
+
+ // The regular seed should be used, so the safe seed manager should be
+ // informed of the active seed state.
+ NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
+ ON_CALL(safe_seed_manager, ShouldRunInSafeMode())
+ .WillByDefault(Return(false));
+ const int minutes = 45;
+ const base::Time seed_fetch_time = base::Time::Now() - base::Minutes(minutes);
+ EXPECT_CALL(safe_seed_manager,
+ DoSetActiveSeedState(kTestSeedSerializedData, kTestSeedSignature,
+ 0, _, seed_fetch_time))
+ .Times(1);
+
+ TestVariationsServiceClient variations_service_client;
+ TestVariationsFieldTrialCreator field_trial_creator(
+ &prefs_, &variations_service_client, &safe_seed_manager);
+
+ // Simulate the seed being stored.
+ prefs_.SetTime(prefs::kVariationsLastFetchTime, seed_fetch_time);
+
+ // Simulate the absence of a milestone by leaving
+ // |prefs::kVariationsSeedMilestone| empty.
+ EXPECT_EQ(0, prefs_.GetInteger(prefs::kVariationsSeedMilestone));
+
+ // Check that field trials are created from the seed. Since the test study has
+ // only one experiment with 100% probability weight, we must be part of it.
+ base::HistogramTester histogram_tester;
+ EXPECT_TRUE(field_trial_creator.SetUpFieldTrials());
+ EXPECT_EQ(base::FieldTrialList::FindFullName(kTestSeedStudyName),
+ kTestSeedExperimentName);
+
+ // Verify metrics.
+ histogram_tester.ExpectUniqueSample("Variations.CreateTrials.SeedExpiry",
+ VariationsSeedExpiry::kNotExpired, 1);
+ histogram_tester.ExpectUniqueSample("Variations.SeedFreshness", minutes, 1);
+ histogram_tester.ExpectUniqueSample("Variations.SeedUsage",
+ SeedUsage::kRegularSeedUsed, 1);
+}
+
+TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_ExpiredSeed) {
DisableTestingConfig();
// When the seed is older than 30 days and older than the binary, no field
@@ -545,7 +582,7 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ExpiredSeed) {
NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
ON_CALL(safe_seed_manager, ShouldRunInSafeMode())
.WillByDefault(Return(false));
- EXPECT_CALL(safe_seed_manager, DoSetActiveSeedState(_, _, _, _)).Times(0);
+ EXPECT_CALL(safe_seed_manager, DoSetActiveSeedState(_, _, _, _, _)).Times(0);
TestVariationsServiceClient variations_service_client;
TestVariationsFieldTrialCreator field_trial_creator(
@@ -560,7 +597,7 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ExpiredSeed) {
// Check that field trials are not created from the expired seed.
base::HistogramTester histogram_tester;
- EXPECT_FALSE(field_trial_creator.SetupFieldTrials());
+ EXPECT_FALSE(field_trial_creator.SetUpFieldTrials());
EXPECT_FALSE(base::FieldTrialList::TrialExists(kTestSeedStudyName));
// Verify metrics. The seed freshness metric should not be recorded for an
@@ -572,9 +609,43 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ExpiredSeed) {
SeedUsage::kExpiredRegularSeedNotUsed, 1);
}
+// Verify that a regular seed is not used when the milestone with which it was
+// fetched is greater than the client's milestone.
+TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_FutureMilestone) {
+ DisableTestingConfig();
+ const int future_seed_milestone = 7890;
+
+ // When the seed is associated with a future milestone (relative to the
+ // client's milestone), no field trials should be created from the seed.
+ // Hence, no active state should be passed to the safe seed manager.
+ NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
+ ON_CALL(safe_seed_manager, ShouldRunInSafeMode())
+ .WillByDefault(Return(false));
+ EXPECT_CALL(safe_seed_manager, DoSetActiveSeedState(_, _, _, _, _)).Times(0);
+
+ TestVariationsServiceClient variations_service_client;
+ TestVariationsFieldTrialCreator field_trial_creator(
+ &prefs_, &variations_service_client, &safe_seed_manager);
+ const base::Time now = base::Time::Now();
+ field_trial_creator.SetBuildTime(now);
+
+ // Simulate a seed from a future milestone.
+ prefs_.SetInteger(prefs::kVariationsSeedMilestone, future_seed_milestone);
+
+ // Check that field trials are not created from the seed.
+ base::HistogramTester histogram_tester;
+ EXPECT_FALSE(field_trial_creator.SetUpFieldTrials());
+ EXPECT_FALSE(base::FieldTrialList::TrialExists(kTestSeedStudyName));
+
+ // Verify metrics.
+ histogram_tester.ExpectUniqueSample(
+ "Variations.SeedUsage", SeedUsage::kRegularSeedForFutureMilestoneNotUsed,
+ 1);
+}
+
// Verify that unexpired safe seeds are used.
TEST_F(FieldTrialCreatorTest,
- SetupFieldTrials_ValidSafeSeed_NewBinaryUsesSeed) {
+ SetUpFieldTrials_ValidSafeSeed_NewBinaryUsesSeed) {
DisableTestingConfig();
const base::Time now = base::Time::Now();
@@ -595,7 +666,8 @@ TEST_F(FieldTrialCreatorTest,
NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
ON_CALL(safe_seed_manager, ShouldRunInSafeMode())
.WillByDefault(Return(true));
- EXPECT_CALL(safe_seed_manager, DoSetActiveSeedState(_, _, _, _)).Times(0);
+ EXPECT_CALL(safe_seed_manager, DoSetActiveSeedState(_, _, _, _, _))
+ .Times(0);
TestVariationsServiceClient variations_service_client;
TestVariationsFieldTrialCreator field_trial_creator(
@@ -610,7 +682,7 @@ TEST_F(FieldTrialCreatorTest,
// study has only one experiment with 100% probability weight, we must be
// part of it.
base::HistogramTester histogram_tester;
- EXPECT_TRUE(field_trial_creator.SetupFieldTrials());
+ EXPECT_TRUE(field_trial_creator.SetUpFieldTrials());
EXPECT_EQ(kTestSafeSeedExperimentName,
base::FieldTrialList::FindFullName(kTestSeedStudyName));
@@ -630,7 +702,7 @@ TEST_F(FieldTrialCreatorTest,
// Verify that Chrome applies the regular variations seed when Chrome should run
// in variations safe mode but the safe seed is empty.
-TEST_F(FieldTrialCreatorTest, SetupFieldTrials_EmptySafeSeed_UsesRegularSeed) {
+TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_EmptySafeSeed_UsesRegularSeed) {
DisableTestingConfig();
NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
@@ -642,7 +714,7 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_EmptySafeSeed_UsesRegularSeed) {
// the active seed state.
EXPECT_CALL(safe_seed_manager,
DoSetActiveSeedState(kTestSeedSerializedData, kTestSeedSignature,
- _, recent_time))
+ _, _, recent_time))
.Times(1);
TestVariationsServiceClient variations_service_client;
@@ -654,7 +726,7 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_EmptySafeSeed_UsesRegularSeed) {
// study has only one experiment with 100% probability weight, we must be part
// of it.
base::HistogramTester histogram_tester;
- EXPECT_TRUE(field_trial_creator.SetupFieldTrials());
+ EXPECT_TRUE(field_trial_creator.SetUpFieldTrials());
EXPECT_EQ(kTestSeedExperimentName,
base::FieldTrialList::FindFullName(kTestSeedStudyName));
@@ -670,7 +742,7 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_EmptySafeSeed_UsesRegularSeed) {
// Verify that Chrome does not apply a variations seed when Chrome should run in
// variations safe mode and a safe seed cannot be loaded.
TEST_F(FieldTrialCreatorTest,
- SetupFieldTrials_CorruptedSafeSeed_DoesNotUseSeed) {
+ SetUpFieldTrials_CorruptedSafeSeed_DoesNotUseSeed) {
DisableTestingConfig();
NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
@@ -678,7 +750,7 @@ TEST_F(FieldTrialCreatorTest,
// When falling back to client-side defaults, the safe seed manager should not
// be informed of the active seed state.
- EXPECT_CALL(safe_seed_manager, DoSetActiveSeedState(_, _, _, _)).Times(0);
+ EXPECT_CALL(safe_seed_manager, DoSetActiveSeedState(_, _, _, _, _)).Times(0);
TestVariationsServiceClient variations_service_client;
TestVariationsFieldTrialCreator field_trial_creator(
@@ -688,7 +760,7 @@ TEST_F(FieldTrialCreatorTest,
base::HistogramTester histogram_tester;
// Verify that field trials were not set up.
- EXPECT_FALSE(field_trial_creator.SetupFieldTrials());
+ EXPECT_FALSE(field_trial_creator.SetUpFieldTrials());
EXPECT_FALSE(base::FieldTrialList::TrialExists(kTestSeedStudyName));
// Verify that Chrome did not apply the safe seed.
@@ -697,7 +769,7 @@ TEST_F(FieldTrialCreatorTest,
}
// Verify that valid safe seeds with missing download times are applied.
-TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ValidSafeSeed_NoLastFetchTime) {
+TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_ValidSafeSeed_NoLastFetchTime) {
DisableTestingConfig();
// With a valid safe seed, the safe seed manager should not be informed of the
@@ -705,7 +777,7 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ValidSafeSeed_NoLastFetchTime) {
// already running in safe mode.
NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
ON_CALL(safe_seed_manager, ShouldRunInSafeMode()).WillByDefault(Return(true));
- EXPECT_CALL(safe_seed_manager, DoSetActiveSeedState(_, _, _, _)).Times(0);
+ EXPECT_CALL(safe_seed_manager, DoSetActiveSeedState(_, _, _, _, _)).Times(0);
TestVariationsServiceClient variations_service_client;
TestVariationsFieldTrialCreator field_trial_creator(
@@ -718,7 +790,7 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ValidSafeSeed_NoLastFetchTime) {
// study has only one experiment with 100% probability weight, we must be part
// of it.
base::HistogramTester histogram_tester;
- EXPECT_TRUE(field_trial_creator.SetupFieldTrials());
+ EXPECT_TRUE(field_trial_creator.SetUpFieldTrials());
EXPECT_EQ(kTestSafeSeedExperimentName,
base::FieldTrialList::FindFullName(kTestSeedStudyName));
@@ -734,15 +806,13 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ValidSafeSeed_NoLastFetchTime) {
// Verify that no seed is applied when (i) safe mode is triggered and (ii) the
// loaded safe seed has expired.
-TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ExpiredSafeSeed) {
+TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_ExpiredSafeSeed) {
DisableTestingConfig();
- // With a valid safe seed, the safe seed manager should not be informed of the
- // active seed state. This is an optimization to avoid saving a safe seed when
- // already running in safe mode.
+ // The safe seed manager should not be informed of the active seed state.
NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
ON_CALL(safe_seed_manager, ShouldRunInSafeMode()).WillByDefault(Return(true));
- EXPECT_CALL(safe_seed_manager, DoSetActiveSeedState(_, _, _, _)).Times(0);
+ EXPECT_CALL(safe_seed_manager, DoSetActiveSeedState(_, _, _, _, _)).Times(0);
TestVariationsServiceClient variations_service_client;
TestVariationsFieldTrialCreator field_trial_creator(
@@ -757,7 +827,7 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ExpiredSafeSeed) {
// Check that field trials are not created from the expired seed.
base::HistogramTester histogram_tester;
- EXPECT_FALSE(field_trial_creator.SetupFieldTrials());
+ EXPECT_FALSE(field_trial_creator.SetUpFieldTrials());
EXPECT_FALSE(base::FieldTrialList::TrialExists(kTestSeedStudyName));
// Verify metrics. The seed freshness metric should not be recorded for an
@@ -770,9 +840,37 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_ExpiredSafeSeed) {
SeedUsage::kExpiredSafeSeedNotUsed, 1);
}
+// Verify that no seed is applied when (i) safe mode is triggered and (ii) the
+// loaded safe seed was fetched with a future milestone.
+TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_SafeSeedForFutureMilestone) {
+ DisableTestingConfig();
+ const int future_seed_milestone = 7890;
+
+ // The safe seed manager should not be informed of the active seed state.
+ NiceMock<MockSafeSeedManager> safe_seed_manager(&prefs_);
+ ON_CALL(safe_seed_manager, ShouldRunInSafeMode()).WillByDefault(Return(true));
+ EXPECT_CALL(safe_seed_manager, DoSetActiveSeedState(_, _, _, _, _)).Times(0);
+
+ TestVariationsServiceClient variations_service_client;
+ TestVariationsFieldTrialCreator field_trial_creator(
+ &prefs_, &variations_service_client, &safe_seed_manager);
+
+ // Simulate a safe seed that was fetched with a future milestone.
+ prefs_.SetInteger(prefs::kVariationsSafeSeedMilestone, future_seed_milestone);
+
+ // Check that field trials are not created from the safe seed.
+ base::HistogramTester histogram_tester;
+ EXPECT_FALSE(field_trial_creator.SetUpFieldTrials());
+ EXPECT_FALSE(base::FieldTrialList::TrialExists(kTestSeedStudyName));
+
+ // Verify metrics.
+ histogram_tester.ExpectUniqueSample(
+ "Variations.SeedUsage", SeedUsage::kSafeSeedForFutureMilestoneNotUsed, 1);
+}
+
#if defined(OS_ANDROID)
-// This is a regression test for https://crbug.com/829527
-TEST_F(FieldTrialCreatorTest, SetupFieldTrials_LoadsCountryOnFirstRun) {
+// This is a regression test for crbug/829527.
+TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_LoadsCountryOnFirstRun) {
DisableTestingConfig();
// Simulate having received a seed in Java during First Run.
@@ -807,7 +905,7 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_LoadsCountryOnFirstRun) {
// single study with an experiment targeting 100% of users in India. Since
// |initial_seed| included the country code for India, this study should be
// active.
- EXPECT_TRUE(field_trial_creator.SetupFieldTrials(
+ EXPECT_TRUE(field_trial_creator.SetUpFieldTrials(
/*variation_ids=*/std::vector<std::string>(),
std::vector<base::FeatureList::FeatureOverrideInfo>(),
/*low_entropy_provider=*/nullptr, std::make_unique<base::FeatureList>(),
@@ -835,10 +933,8 @@ TEST_F(FieldTrialCreatorTest, ClientFilterableState_HardwareClass) {
field_trial_creator.GetClientFilterableStateForVersion(current_version);
EXPECT_NE(client_filterable_state->hardware_class, std::string());
}
-#endif // OS_ANDROID
+#endif // defined(OS_ANDROID)
-#if !defined(OS_ANDROID)
-// TODO(crbug/1248239): Enable Extended Variations Safe Mode on Android.
TEST_F(FieldTrialCreatorSafeModeExperimentTest, OptOutOfExperiment) {
std::unique_ptr<PrefService> pref_service(CreatePrefService());
@@ -847,15 +943,17 @@ TEST_F(FieldTrialCreatorSafeModeExperimentTest, OptOutOfExperiment) {
ON_CALL(safe_seed_manager, ShouldRunInSafeMode())
.WillByDefault(Return(false));
+ version_info::Channel channel = version_info::Channel::DEV;
NiceMock<MockVariationsServiceClient> variations_service_client;
ON_CALL(variations_service_client, GetChannel())
- .WillByDefault(Return(version_info::Channel::DEV));
+ .WillByDefault(Return(channel));
TestVariationsFieldTrialCreator field_trial_creator(
- pref_service.get(), &variations_service_client, &safe_seed_manager);
+ pref_service.get(), &variations_service_client, &safe_seed_manager,
+ channel);
base::HistogramTester histogram_tester;
- ASSERT_TRUE(field_trial_creator.SetupFieldTrials(
+ ASSERT_TRUE(field_trial_creator.SetUpFieldTrials(
/*extend_variations_safe_mode=*/false));
// Verify that the experiment is not active and that the WritePrefsTime metric
@@ -874,15 +972,15 @@ INSTANTIATE_TEST_SUITE_P(
StartupVisibilityTestParams{
.test_name = "UnknownVisibility",
.startup_visibility = metrics::StartupVisibility::kUnknown,
- .is_trial_active = true},
+ .extend_safe_mode = true},
StartupVisibilityTestParams{
.test_name = "BackgroundVisibility",
.startup_visibility = metrics::StartupVisibility::kBackground,
- .is_trial_active = false},
+ .extend_safe_mode = false},
StartupVisibilityTestParams{
.test_name = "ForegroundVisibility",
.startup_visibility = metrics::StartupVisibility::kForeground,
- .is_trial_active = true}),
+ .extend_safe_mode = true}),
[](const ::testing::TestParamInfo<StartupVisibilityTestParams>& params) {
return params.param.test_name;
});
@@ -897,18 +995,19 @@ TEST_P(FieldTrialCreatorTestWithStartupVisibility,
.WillByDefault(Return(false));
NiceMock<MockVariationsServiceClient> variations_service_client;
+ version_info::Channel channel = version_info::Channel::DEV;
ON_CALL(variations_service_client, GetChannel())
- .WillByDefault(Return(version_info::Channel::DEV));
+ .WillByDefault(Return(channel));
StartupVisibilityTestParams params = GetParam();
TestVariationsFieldTrialCreator field_trial_creator(
pref_service.get(), &variations_service_client, &safe_seed_manager,
- base::FilePath(), params.startup_visibility);
- ASSERT_TRUE(field_trial_creator.SetupFieldTrials());
+ channel, base::FilePath(), params.startup_visibility);
+ ASSERT_TRUE(field_trial_creator.SetUpFieldTrials());
- // Verify that the experiment is active (or inactive).
- EXPECT_EQ(base::FieldTrialList::IsTrialActive(kExtendedSafeModeTrial),
- params.is_trial_active);
+ // Verify that MaybeExtendVariationsSafeMode() was (or wasn't) called.
+ EXPECT_EQ(field_trial_creator.was_maybe_extend_variations_safe_mode_called(),
+ params.extend_safe_mode);
base::FeatureList::ClearInstanceForTesting();
}
@@ -924,18 +1023,26 @@ TEST_F(FieldTrialCreatorSafeModeExperimentTest,
ON_CALL(safe_seed_manager, ShouldRunInSafeMode())
.WillByDefault(Return(false));
+// For desktop and iOS, the Extended Variations Safe Mode experiment is enabled
+// on pre-stable channels; for Android Chrome, on canary and dev.
+#if defined(OS_ANDROID)
std::vector<version_info::Channel> channels = {version_info::Channel::BETA,
version_info::Channel::STABLE};
+#else
+ std::vector<version_info::Channel> channels = {version_info::Channel::STABLE};
+#endif // defined(OS_ANDROID)
+
for (const version_info::Channel channel : channels) {
NiceMock<MockVariationsServiceClient> variations_service_client;
ON_CALL(variations_service_client, GetChannel())
.WillByDefault(Return(channel));
TestVariationsFieldTrialCreator field_trial_creator(
- pref_service.get(), &variations_service_client, &safe_seed_manager);
+ pref_service.get(), &variations_service_client, &safe_seed_manager,
+ channel);
base::HistogramTester histogram_tester;
- ASSERT_TRUE(field_trial_creator.SetupFieldTrials());
+ ASSERT_TRUE(field_trial_creator.SetUpFieldTrials());
// Verify that the experiment is not active.
EXPECT_FALSE(base::FieldTrialList::IsTrialActive(kExtendedSafeModeTrial));
@@ -957,21 +1064,25 @@ TEST_F(FieldTrialCreatorSafeModeExperimentTest,
std::unique_ptr<PrefService> pref_service(CreatePrefService());
NiceMock<MockVariationsServiceClient> variations_service_client;
+ version_info::Channel channel = version_info::Channel::CANARY;
ON_CALL(variations_service_client, GetChannel())
- .WillByDefault(Return(version_info::Channel::CANARY));
+ .WillByDefault(Return(channel));
// Ensure that variations safe mode is not triggered.
NiceMock<MockSafeSeedManager> safe_seed_manager(pref_service.get());
ON_CALL(safe_seed_manager, ShouldRunInSafeMode())
.WillByDefault(Return(false));
- TestVariationsFieldTrialCreator field_trial_creator(
- pref_service.get(), &variations_service_client, &safe_seed_manager);
-
+ // Assign the client to a specific experiment group before creating the
+ // TestVariationsFieldTrialCreator so that the CleanExitBeacon uses the
+ // desired group.
int active_group = SetUpExtendedSafeModeExperiment(kControlGroup);
+ TestVariationsFieldTrialCreator field_trial_creator(
+ pref_service.get(), &variations_service_client, &safe_seed_manager,
+ channel);
base::HistogramTester histogram_tester;
- ASSERT_TRUE(field_trial_creator.SetupFieldTrials());
+ ASSERT_TRUE(field_trial_creator.SetUpFieldTrials());
// Verify that the field trial is active and that the client is in the
// control group.
@@ -979,97 +1090,12 @@ TEST_F(FieldTrialCreatorSafeModeExperimentTest,
EXPECT_EQ(active_group,
base::FieldTrialList::FindValue(kExtendedSafeModeTrial));
- // Check that no prefs were written and that the WritePrefsTime metric was not
+ // Check that no prefs were written and that the WritePrefsTime metric was
// recorded.
std::string pref_file_contents;
ASSERT_TRUE(base::ReadFileToString(prefs_file(), &pref_file_contents));
EXPECT_EQ(kEmptyPrefsFile, pref_file_contents);
histogram_tester.ExpectTotalCount(
- "Variations.ExtendedSafeMode.WritePrefsTime", 0);
-
- // Verify that the Variations Safe Mode file does not exist.
- EXPECT_FALSE(base::PathExists(
- user_data_dir_path().Append(variations::kVariationsFilename)));
-}
-
-TEST_F(FieldTrialCreatorSafeModeExperimentTest,
- EnableExperimentOnDev_WriteSynchronouslyViaPrefServiceGroup) {
- std::unique_ptr<PrefService> pref_service(CreatePrefService());
-
- NiceMock<MockVariationsServiceClient> variations_service_client;
- ON_CALL(variations_service_client, GetChannel())
- .WillByDefault(Return(version_info::Channel::DEV));
-
- // Ensure that variations safe mode is not triggered.
- NiceMock<MockSafeSeedManager> safe_seed_manager(pref_service.get());
- ON_CALL(safe_seed_manager, ShouldRunInSafeMode())
- .WillByDefault(Return(false));
-
- TestVariationsFieldTrialCreator field_trial_creator(
- pref_service.get(), &variations_service_client, &safe_seed_manager,
- user_data_dir_path());
-
- int active_group =
- SetUpExtendedSafeModeExperiment(kWriteSynchronouslyViaPrefServiceGroup);
-
- base::HistogramTester histogram_tester;
- ASSERT_TRUE(field_trial_creator.SetupFieldTrials());
-
- // Verify that the field trial is active and that the client is in the
- // WriteSynchronouslyViaPrefService group.
- EXPECT_TRUE(base::FieldTrialList::IsTrialActive(kExtendedSafeModeTrial));
- EXPECT_EQ(active_group,
- base::FieldTrialList::FindValue(kExtendedSafeModeTrial));
-
- // Check that prefs were written and do not contain kStabilityExitedCleanly.
- // Also, check that the WritePrefsTime metric was recorded.
- std::string pref_file_contents;
- ASSERT_TRUE(base::ReadFileToString(prefs_file(), &pref_file_contents));
- EXPECT_NE(kEmptyPrefsFile, pref_file_contents);
- EXPECT_FALSE(base::Contains(pref_file_contents, "exited_cleanly"));
- histogram_tester.ExpectTotalCount(
- "Variations.ExtendedSafeMode.WritePrefsTime", 1);
-
- // Verify that the Variations Safe Mode file does not exist.
- EXPECT_FALSE(base::PathExists(
- user_data_dir_path().Append(variations::kVariationsFilename)));
-}
-
-TEST_F(FieldTrialCreatorSafeModeExperimentTest,
- EnableExperimentOnDev_SignalAndWriteSynchronouslyViaPrefServiceGroup) {
- std::unique_ptr<PrefService> pref_service(CreatePrefService());
-
- NiceMock<MockVariationsServiceClient> variations_service_client;
- ON_CALL(variations_service_client, GetChannel())
- .WillByDefault(Return(version_info::Channel::DEV));
-
- // Ensure that variations safe mode is not triggered.
- NiceMock<MockSafeSeedManager> safe_seed_manager(pref_service.get());
- ON_CALL(safe_seed_manager, ShouldRunInSafeMode())
- .WillByDefault(Return(false));
-
- TestVariationsFieldTrialCreator field_trial_creator(
- pref_service.get(), &variations_service_client, &safe_seed_manager,
- user_data_dir_path());
-
- int active_group = SetUpExtendedSafeModeExperiment(
- kSignalAndWriteSynchronouslyViaPrefServiceGroup);
-
- base::HistogramTester histogram_tester;
- ASSERT_TRUE(field_trial_creator.SetupFieldTrials());
-
- // Verify that the field trial is active and that the client is in the
- // SignalAndWriteSynchronouslyViaPrefService group.
- EXPECT_TRUE(base::FieldTrialList::IsTrialActive(kExtendedSafeModeTrial));
- EXPECT_EQ(active_group,
- base::FieldTrialList::FindValue(kExtendedSafeModeTrial));
-
- // Check that prefs were written and contain kStabilityExitedCleanly. Also,
- // check that the WritePrefsTime metric was recorded.
- std::string pref_file_contents;
- ASSERT_TRUE(base::ReadFileToString(prefs_file(), &pref_file_contents));
- EXPECT_TRUE(base::Contains(pref_file_contents, "\"exited_cleanly\":false"));
- histogram_tester.ExpectTotalCount(
"Variations.ExtendedSafeMode.WritePrefsTime", 1);
// Verify that the Variations Safe Mode file does not exist.
@@ -1082,23 +1108,26 @@ TEST_F(FieldTrialCreatorSafeModeExperimentTest,
std::unique_ptr<PrefService> pref_service(CreatePrefService());
NiceMock<MockVariationsServiceClient> variations_service_client;
+ version_info::Channel channel = version_info::Channel::DEV;
ON_CALL(variations_service_client, GetChannel())
- .WillByDefault(Return(version_info::Channel::DEV));
+ .WillByDefault(Return(channel));
// Ensure that variations safe mode is not triggered.
NiceMock<MockSafeSeedManager> safe_seed_manager(pref_service.get());
ON_CALL(safe_seed_manager, ShouldRunInSafeMode())
.WillByDefault(Return(false));
- TestVariationsFieldTrialCreator field_trial_creator(
- pref_service.get(), &variations_service_client, &safe_seed_manager,
- user_data_dir_path());
-
+ // Assign the client to a specific experiment group before creating the
+ // TestVariationsFieldTrialCreator so that the CleanExitBeacon uses the
+ // desired group.
int active_group =
SetUpExtendedSafeModeExperiment(kSignalAndWriteViaFileUtilGroup);
+ TestVariationsFieldTrialCreator field_trial_creator(
+ pref_service.get(), &variations_service_client, &safe_seed_manager,
+ channel, user_data_dir_path());
base::HistogramTester histogram_tester;
- ASSERT_TRUE(field_trial_creator.SetupFieldTrials());
+ ASSERT_TRUE(field_trial_creator.SetUpFieldTrials());
// Verify that the field trial is active and that the client is in the
// SignalAndWriteViaFileUtil group.
@@ -1127,6 +1156,5 @@ TEST_F(FieldTrialCreatorSafeModeExperimentTest,
ASSERT_TRUE(base::ReadFileToString(prefs_file(), &pref_file_contents));
EXPECT_EQ(kEmptyPrefsFile, pref_file_contents);
}
-#endif // !defined(OS_ANDROID)
} // namespace variations
diff --git a/chromium/components/variations/service/variations_safe_mode_constants.cc b/chromium/components/variations/service/variations_safe_mode_constants.cc
index f3b5732737c..8b73a7730f2 100644
--- a/chromium/components/variations/service/variations_safe_mode_constants.cc
+++ b/chromium/components/variations/service/variations_safe_mode_constants.cc
@@ -9,13 +9,9 @@ namespace variations {
const base::FilePath::CharType kVariationsFilename[] =
FILE_PATH_LITERAL("Variations");
-const char kExtendedSafeModeTrial[] = "ExtendedVariationsSafeMode2";
-const char kControlGroup[] = "Control2";
-const char kDefaultGroup[] = "Default2";
-const char kSignalAndWriteSynchronouslyViaPrefServiceGroup[] =
- "SignalAndWriteSynchronouslyViaPrefService";
-const char kSignalAndWriteViaFileUtilGroup[] = "SignalAndWriteViaFileUtil";
-const char kWriteSynchronouslyViaPrefServiceGroup[] =
- "WriteSynchronouslyViaPrefService";
+const char kExtendedSafeModeTrial[] = "ExtendedVariationsSafeMode4";
+const char kControlGroup[] = "Control4";
+const char kDefaultGroup[] = "Default4";
+const char kSignalAndWriteViaFileUtilGroup[] = "SignalAndWriteViaFileUtil4";
} // namespace variations
diff --git a/chromium/components/variations/service/variations_safe_mode_constants.h b/chromium/components/variations/service/variations_safe_mode_constants.h
index 2295c972b3d..87695d2927d 100644
--- a/chromium/components/variations/service/variations_safe_mode_constants.h
+++ b/chromium/components/variations/service/variations_safe_mode_constants.h
@@ -20,9 +20,7 @@ extern const base::FilePath::CharType kVariationsFilename[];
extern const char kExtendedSafeModeTrial[];
extern const char kControlGroup[];
extern const char kDefaultGroup[];
-extern const char kSignalAndWriteSynchronouslyViaPrefServiceGroup[];
extern const char kSignalAndWriteViaFileUtilGroup[];
-extern const char kWriteSynchronouslyViaPrefServiceGroup[];
} // namespace variations
diff --git a/chromium/components/variations/service/variations_service.cc b/chromium/components/variations/service/variations_service.cc
index 6173c8e4c68..b812395e6c3 100644
--- a/chromium/components/variations/service/variations_service.cc
+++ b/chromium/components/variations/service/variations_service.cc
@@ -67,10 +67,6 @@
#endif // OS_ANDROID
namespace variations {
-
-const base::Feature kHttpRetryFeature{"VariationsHttpRetry",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
namespace {
// Constants used for encrypting the if-none-match header if we are retrieving a
@@ -482,12 +478,10 @@ GURL VariationsService::GetVariationsServerURL(HttpOptions http_options) {
}
// Add milestone to the request URL.
- std::string version = version_info::GetVersionNumber();
- std::vector<std::string> version_parts = base::SplitString(
- version, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- if (version_parts.size() > 0) {
- server_url = net::AppendOrReplaceQueryParameter(server_url, "milestone",
- version_parts[0]);
+ const std::string milestone = version_info::GetMajorVersionNumber();
+ if (!milestone.empty()) {
+ server_url =
+ net::AppendOrReplaceQueryParameter(server_url, "milestone", milestone);
}
DCHECK(server_url.is_valid());
@@ -720,12 +714,9 @@ void VariationsService::InitResourceRequestedAllowedNotifier() {
void VariationsService::StartRepeatedVariationsSeedFetch() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // Initialize the Variations server URL.
+ // Initialize Variations server URLs.
variations_server_url_ = GetVariationsServerURL(USE_HTTPS);
-
- // Initialize the fallback HTTP URL if the HTTP retry feature is enabled.
- if (base::FeatureList::IsEnabled(kHttpRetryFeature))
- insecure_variations_server_url_ = GetVariationsServerURL(USE_HTTP);
+ insecure_variations_server_url_ = GetVariationsServerURL(USE_HTTP);
DCHECK(!request_scheduler_);
request_scheduler_.reset(VariationsRequestScheduler::Create(
@@ -958,13 +949,13 @@ std::string VariationsService::GetLatestCountry() const {
return field_trial_creator_.GetLatestCountry();
}
-bool VariationsService::SetupFieldTrials(
+bool VariationsService::SetUpFieldTrials(
const std::vector<std::string>& variation_ids,
const std::vector<base::FeatureList::FeatureOverrideInfo>& extra_overrides,
std::unique_ptr<base::FeatureList> feature_list,
variations::PlatformFieldTrials* platform_field_trials,
bool extend_variations_safe_mode) {
- return field_trial_creator_.SetupFieldTrials(
+ return field_trial_creator_.SetUpFieldTrials(
variation_ids, extra_overrides, CreateLowEntropyProvider(),
std::move(feature_list), state_manager_, platform_field_trials,
&safe_seed_manager_, state_manager_->GetLowEntropySource(),
@@ -1005,8 +996,9 @@ std::string VariationsService::GetStoredPermanentCountry() {
local_state_->GetList(prefs::kVariationsPermanentConsistencyCountry);
std::string stored_country;
- if (list_value->GetList().size() == 2) {
- list_value->GetString(1, &stored_country);
+ base::Value::ConstListView list_view = list_value->GetList();
+ if (list_view.size() == 2 && list_view[1].is_string()) {
+ stored_country = list_view[1].GetString();
}
return stored_country;
diff --git a/chromium/components/variations/service/variations_service.h b/chromium/components/variations/service/variations_service.h
index 850b1e73278..a0883a82349 100644
--- a/chromium/components/variations/service/variations_service.h
+++ b/chromium/components/variations/service/variations_service.h
@@ -11,7 +11,7 @@
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/observer_list.h"
@@ -59,12 +59,8 @@ namespace variations {
class DeviceVariationsRestrictionByPolicyApplicator;
#endif
-// If enabled, seed fetches will be retried over HTTP after an HTTPS request
-// fails.
-extern const base::Feature kHttpRetryFeature;
-
-// Used to setup field trials based on stored variations seed data, and fetch
-// new seed data from the variations server.
+// Used to (a) set up field trials based on stored variations seed data and (b)
+// fetch new seed data from the variations server.
class VariationsService
: public web_resource::ResourceRequestAllowedNotifier::Observer {
public:
@@ -190,9 +186,9 @@ class VariationsService
return resource_request_allowed_notifier_.get();
}
- // Wrapper around VariationsFieldTrialCreator::SetupFieldTrials().
+ // Wrapper around VariationsFieldTrialCreator::SetUpFieldTrials().
// TODO(crbug/1245646): Remove |extend_variations_safe_mode| param.
- bool SetupFieldTrials(
+ bool SetUpFieldTrials(
const std::vector<std::string>& variation_ids,
const std::vector<base::FeatureList::FeatureOverrideInfo>&
extra_overrides,
@@ -357,15 +353,15 @@ class VariationsService
std::unique_ptr<VariationsServiceClient> client_;
// The pref service used to store persist the variations seed.
- PrefService* local_state_;
+ raw_ptr<PrefService> local_state_;
// Used for instantiating entropy providers for variations seed simulation.
// Weak pointer.
- metrics::MetricsStateManager* state_manager_;
+ raw_ptr<metrics::MetricsStateManager> state_manager_;
// Used to obtain policy-related preferences. Depending on the platform, will
// either be Local State or Profile prefs.
- PrefService* policy_pref_service_;
+ raw_ptr<PrefService> policy_pref_service_;
// Contains the scheduler instance that handles timing for requests to the
// server. Initially NULL and instantiated when the initial fetch is
diff --git a/chromium/components/variations/service/variations_service_unittest.cc b/chromium/components/variations/service/variations_service_unittest.cc
index a8409da11d9..71905308c67 100644
--- a/chromium/components/variations/service/variations_service_unittest.cc
+++ b/chromium/components/variations/service/variations_service_unittest.cc
@@ -17,7 +17,7 @@
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/json/json_string_value_serializer.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
@@ -359,7 +359,7 @@ class VariationsServiceTest : public ::testing::Test {
protected:
TestingPrefServiceSimple prefs_;
- network::TestNetworkConnectionTracker* network_tracker_;
+ raw_ptr<network::TestNetworkConnectionTracker> network_tracker_;
private:
base::test::TaskEnvironment task_environment_;
diff --git a/chromium/components/variations/study_filtering_unittest.cc b/chromium/components/variations/study_filtering_unittest.cc
index d0e14069a5b..cef6c287506 100644
--- a/chromium/components/variations/study_filtering_unittest.cc
+++ b/chromium/components/variations/study_filtering_unittest.cc
@@ -13,7 +13,6 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/cxx17_backports.h"
-#include "base/macros.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
diff --git a/chromium/components/variations/synthetic_trial_registry_unittest.cc b/chromium/components/variations/synthetic_trial_registry_unittest.cc
index d786e1045bd..97c452ebf64 100644
--- a/chromium/components/variations/synthetic_trial_registry_unittest.cc
+++ b/chromium/components/variations/synthetic_trial_registry_unittest.cc
@@ -193,8 +193,8 @@ TEST_F(SyntheticTrialRegistryTest, RegisterExternalExperiments_WithAllowlist) {
TEST_F(SyntheticTrialRegistryTest, GetSyntheticFieldTrialActiveGroups) {
SyntheticTrialRegistry registry;
- // Instantiate and setup the corresponding singleton observer which tracks the
- // creation of all SyntheticTrialGroups.
+ // Instantiate and set up the corresponding singleton observer which tracks
+ // the creation of all SyntheticTrialGroups.
registry.AddSyntheticTrialObserver(
SyntheticTrialsActiveGroupIdProvider::GetInstance());
diff --git a/chromium/components/variations/synthetic_trials_active_group_id_provider.h b/chromium/components/variations/synthetic_trials_active_group_id_provider.h
index c6b4eff33d5..f508ae790c9 100644
--- a/chromium/components/variations/synthetic_trials_active_group_id_provider.h
+++ b/chromium/components/variations/synthetic_trials_active_group_id_provider.h
@@ -8,7 +8,6 @@
#include <vector>
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "components/variations/active_field_trials.h"
#include "components/variations/synthetic_trials.h"
diff --git a/chromium/components/variations/variations_associated_data.cc b/chromium/components/variations/variations_associated_data.cc
index 551b6591b2d..25100ac5382 100644
--- a/chromium/components/variations/variations_associated_data.cc
+++ b/chromium/components/variations/variations_associated_data.cc
@@ -8,7 +8,6 @@
#include <utility>
#include <vector>
-#include "base/macros.h"
#include "base/memory/singleton.h"
#include "base/metrics/field_trial_param_associator.h"
#include "base/metrics/field_trial_params.h"
diff --git a/chromium/components/variations/variations_associated_data_unittest.cc b/chromium/components/variations/variations_associated_data_unittest.cc
index 110c81375cc..4ffe5d4c188 100644
--- a/chromium/components/variations/variations_associated_data_unittest.cc
+++ b/chromium/components/variations/variations_associated_data_unittest.cc
@@ -4,7 +4,6 @@
#include "components/variations/variations_associated_data.h"
-#include "base/macros.h"
#include "base/metrics/field_trial.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/variations/variations_crash_keys_chromeos.h b/chromium/components/variations/variations_crash_keys_chromeos.h
index eebd2abb7cd..dc7c6e9dfea 100644
--- a/chromium/components/variations/variations_crash_keys_chromeos.h
+++ b/chromium/components/variations/variations_crash_keys_chromeos.h
@@ -6,7 +6,7 @@
#define COMPONENTS_VARIATIONS_VARIATIONS_CRASH_KEYS_CHROMEOS_H_
#include "base/component_export.h"
-#include "base/sequenced_task_runner.h"
+#include "base/task/sequenced_task_runner.h"
#include "components/variations/variations_crash_keys.h"
namespace variations {
diff --git a/chromium/components/variations/variations_ids_provider.h b/chromium/components/variations/variations_ids_provider.h
index 84bcd138738..525e3824ab9 100644
--- a/chromium/components/variations/variations_ids_provider.h
+++ b/chromium/components/variations/variations_ids_provider.h
@@ -13,7 +13,7 @@
#include "base/component_export.h"
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/observer_list.h"
#include "base/synchronization/lock.h"
@@ -285,7 +285,7 @@ class COMPONENT_EXPORT(VARIATIONS) VariationsIdsProvider
// https://crbug.com/1051937 this isn't currently possible.
base::ObserverList<Observer>::Unchecked observer_list_;
- const VariationsClient* variations_client_ = nullptr;
+ raw_ptr<const VariationsClient> variations_client_ = nullptr;
};
} // namespace variations
diff --git a/chromium/components/variations/variations_params_manager.h b/chromium/components/variations/variations_params_manager.h
index 8dbecc1ff61..e16d1546ec9 100644
--- a/chromium/components/variations/variations_params_manager.h
+++ b/chromium/components/variations/variations_params_manager.h
@@ -10,7 +10,6 @@
#include <set>
#include <string>
-#include "base/macros.h"
#include "base/test/scoped_field_trial_list_resetter.h"
namespace base {
@@ -84,7 +83,7 @@ class VariationParamsManager {
//
// This static method is useful in situations where using
// VariationParamsManager directly would have resulted in initializing
- // FieldTrialList twice (once from ChromeBrowserMainParts::SetupFieldTrials
+ // FieldTrialList twice (once from ChromeBrowserMainParts::SetUpFieldTrials
// and once from VariationParamsManager).
static void AppendVariationParams(
const std::string& trial_name,
diff --git a/chromium/components/variations/variations_request_scheduler.h b/chromium/components/variations/variations_request_scheduler.h
index 85de6db1f1f..f0edb94142c 100644
--- a/chromium/components/variations/variations_request_scheduler.h
+++ b/chromium/components/variations/variations_request_scheduler.h
@@ -8,7 +8,6 @@
#include "base/bind.h"
#include "base/component_export.h"
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
diff --git a/chromium/components/variations/variations_request_scheduler_mobile.h b/chromium/components/variations/variations_request_scheduler_mobile.h
index d40fbf5894d..c7a02d505bc 100644
--- a/chromium/components/variations/variations_request_scheduler_mobile.h
+++ b/chromium/components/variations/variations_request_scheduler_mobile.h
@@ -8,7 +8,7 @@
#include "base/bind.h"
#include "base/component_export.h"
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/timer/timer.h"
#include "components/variations/variations_request_scheduler.h"
@@ -16,12 +16,12 @@ class PrefService;
namespace variations {
-// A specialized VariationsRequestScheduler that manages request cycles for
+// A specialized VariationsRequestScheduler that manages request cycles for the
// VariationsService on mobile platforms.
class COMPONENT_EXPORT(VARIATIONS) VariationsRequestSchedulerMobile
: public VariationsRequestScheduler {
public:
- // |task} is the closure to call when the scheduler deems ready. |local_state|
+ // |task| is the closure to call when the scheduler deems ready. |local_state|
// is the PrefService that contains the time of the last fetch.
VariationsRequestSchedulerMobile(const base::RepeatingClosure& task,
PrefService* local_state);
@@ -33,7 +33,7 @@ class COMPONENT_EXPORT(VARIATIONS) VariationsRequestSchedulerMobile
~VariationsRequestSchedulerMobile() override;
- // Base class overrides.
+ // VariationsRequestScheduler:
void Start() override;
void Reset() override;
void OnAppEnterForeground() override;
@@ -47,7 +47,7 @@ class COMPONENT_EXPORT(VARIATIONS) VariationsRequestSchedulerMobile
OnAppEnterForegroundOnStartup);
// The local state instance that provides the last fetch time.
- PrefService* local_state_;
+ raw_ptr<PrefService> local_state_;
// Timer used for triggering a delayed fetch for ScheduleFetch().
base::OneShotTimer schedule_fetch_timer_;
diff --git a/chromium/components/variations/variations_seed_processor.cc b/chromium/components/variations/variations_seed_processor.cc
index 010f43f2efa..dfe929a01a9 100644
--- a/chromium/components/variations/variations_seed_processor.cc
+++ b/chromium/components/variations/variations_seed_processor.cc
@@ -12,6 +12,7 @@
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/metrics/field_trial.h"
+#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/utf_string_conversions.h"
#include "components/variations/client_filterable_state.h"
@@ -188,11 +189,9 @@ bool ShouldForceExperiment(const Study_Experiment& experiment,
} // namespace
-VariationsSeedProcessor::VariationsSeedProcessor() {
-}
+VariationsSeedProcessor::VariationsSeedProcessor() = default;
-VariationsSeedProcessor::~VariationsSeedProcessor() {
-}
+VariationsSeedProcessor::~VariationsSeedProcessor() = default;
void VariationsSeedProcessor::CreateTrialsFromSeed(
const VariationsSeed& seed,
@@ -200,6 +199,8 @@ void VariationsSeedProcessor::CreateTrialsFromSeed(
const UIStringOverrideCallback& override_callback,
const base::FieldTrial::EntropyProvider* low_entropy_provider,
base::FeatureList* feature_list) {
+ base::UmaHistogramCounts1000("Variations.AppliedSeed.StudyCount",
+ seed.study().size());
std::vector<ProcessedStudy> filtered_studies;
VariationsLayers layers(seed, low_entropy_provider);
FilterAndValidateStudies(seed, client_state, layers, &filtered_studies);
diff --git a/chromium/components/variations/variations_seed_processor.h b/chromium/components/variations/variations_seed_processor.h
index d26f298d018..afcb2322d2a 100644
--- a/chromium/components/variations/variations_seed_processor.h
+++ b/chromium/components/variations/variations_seed_processor.h
@@ -13,7 +13,6 @@
#include "base/compiler_specific.h"
#include "base/component_export.h"
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "base/metrics/field_trial.h"
#include "base/version.h"
#include "components/variations/proto/study.pb.h"
diff --git a/chromium/components/variations/variations_seed_processor_unittest.cc b/chromium/components/variations/variations_seed_processor_unittest.cc
index 567f55f0a56..827118f102b 100644
--- a/chromium/components/variations/variations_seed_processor_unittest.cc
+++ b/chromium/components/variations/variations_seed_processor_unittest.cc
@@ -10,6 +10,7 @@
#include <map>
#include <memory>
#include <utility>
+#include <vector>
#include "base/bind.h"
#include "base/callback_helpers.h"
@@ -17,10 +18,10 @@
#include "base/cxx17_backports.h"
#include "base/feature_list.h"
#include "base/format_macros.h"
-#include "base/macros.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_entropy_provider.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_field_trial_list_resetter.h"
@@ -175,7 +176,7 @@ class VariationsSeedProcessorTest : public ::testing::Test {
client_state.reference_date = base::Time::Now();
client_state.version = base::Version("20.0.0.0");
client_state.channel = Study::STABLE;
- client_state.form_factor = Study::DESKTOP;
+ client_state.form_factor = Study::PHONE;
client_state.platform = Study::PLATFORM_ANDROID;
base::FeatureList feature_list;
@@ -190,6 +191,29 @@ class VariationsSeedProcessorTest : public ::testing::Test {
TestOverrideStringCallback override_callback_;
};
+TEST_F(VariationsSeedProcessorTest, EmitStudyCountMetric) {
+ struct StudyCountMetricTestParams {
+ VariationsSeed seed;
+ int expected_study_count;
+ };
+
+ VariationsSeed zero_study_seed;
+ VariationsSeed one_study_seed;
+ Study* study = one_study_seed.add_study();
+ study->set_name("MyStudy");
+ AddExperiment("Enabled", 1, study);
+ std::vector<StudyCountMetricTestParams> test_cases = {
+ {.seed = zero_study_seed, .expected_study_count = 0},
+ {.seed = one_study_seed, .expected_study_count = 1}};
+
+ for (const StudyCountMetricTestParams& test_case : test_cases) {
+ base::HistogramTester histogram_tester;
+ CreateTrialsFromSeed(test_case.seed);
+ histogram_tester.ExpectUniqueSample("Variations.AppliedSeed.StudyCount",
+ test_case.expected_study_count, 1);
+ }
+}
+
TEST_F(VariationsSeedProcessorTest, AllowForceGroupAndVariationId) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1);
diff --git a/chromium/components/variations/variations_seed_simulator.h b/chromium/components/variations/variations_seed_simulator.h
index 90bfedca2bb..d24269e34d7 100644
--- a/chromium/components/variations/variations_seed_simulator.h
+++ b/chromium/components/variations/variations_seed_simulator.h
@@ -10,7 +10,6 @@
#include "base/compiler_specific.h"
#include "base/component_export.h"
-#include "base/macros.h"
#include "base/metrics/field_trial.h"
#include "base/version.h"
#include "components/variations/proto/study.pb.h"
diff --git a/chromium/components/variations/variations_seed_simulator_unittest.cc b/chromium/components/variations/variations_seed_simulator_unittest.cc
index 42840221222..8b90004e6cd 100644
--- a/chromium/components/variations/variations_seed_simulator_unittest.cc
+++ b/chromium/components/variations/variations_seed_simulator_unittest.cc
@@ -8,7 +8,6 @@
#include <map>
-#include "base/macros.h"
#include "base/strings/stringprintf.h"
#include "base/test/mock_entropy_provider.h"
#include "components/variations/processed_study.h"
diff --git a/chromium/components/variations/variations_seed_store.cc b/chromium/components/variations/variations_seed_store.cc
index cd43ff314d9..7f2a99c3883 100644
--- a/chromium/components/variations/variations_seed_store.cc
+++ b/chromium/components/variations/variations_seed_store.cc
@@ -10,7 +10,6 @@
#include "base/base64.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
-#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_math.h"
#include "base/strings/string_number_conversions.h"
@@ -20,6 +19,7 @@
#include "components/variations/client_filterable_state.h"
#include "components/variations/pref_names.h"
#include "components/variations/proto/variations_seed.pb.h"
+#include "components/version_info/version_info.h"
#include "crypto/signature_verifier.h"
#include "third_party/protobuf/src/google/protobuf/io/coded_stream.h"
#include "third_party/zlib/google/compression_utils.h"
@@ -116,10 +116,10 @@ UpdateSeedDateResult GetSeedDateChangeState(
StoreSeedResult Uncompress(const std::string& compressed, std::string* result) {
DCHECK(result);
if (!compression::GzipUncompress(compressed, result))
- return StoreSeedResult::FAILED_UNGZIP;
+ return StoreSeedResult::kFailedUngzip;
if (result->empty())
- return StoreSeedResult::FAILED_EMPTY_GZIP_CONTENTS;
- return StoreSeedResult::SUCCESS;
+ return StoreSeedResult::kFailedEmptyGzipContents;
+ return StoreSeedResult::kSuccess;
}
} // namespace
@@ -156,43 +156,6 @@ bool VariationsSeedStore::LoadSeed(VariationsSeed* seed,
return true;
}
-StoreSeedResult VariationsSeedStore::ResolveDelta(
- const std::string& delta_bytes,
- std::string* seed_bytes) {
- DCHECK(seed_bytes);
- std::string existing_seed_bytes;
- LoadSeedResult read_result =
- ReadSeedData(SeedType::LATEST, &existing_seed_bytes);
- if (read_result != LoadSeedResult::kSuccess)
- return StoreSeedResult::FAILED_DELTA_READ_SEED;
- if (!ApplyDeltaPatch(existing_seed_bytes, delta_bytes, seed_bytes))
- return StoreSeedResult::FAILED_DELTA_APPLY;
- return StoreSeedResult::SUCCESS;
-}
-
-StoreSeedResult VariationsSeedStore::ResolveInstanceManipulations(
- const std::string& data,
- const InstanceManipulations& im,
- std::string* seed_bytes) {
- DCHECK(seed_bytes);
- // If the data is gzip compressed, first uncompress it.
- std::string ungzipped_data;
- if (im.gzip_compressed) {
- StoreSeedResult result = Uncompress(data, &ungzipped_data);
- if (result != StoreSeedResult::SUCCESS)
- return result;
- } else {
- ungzipped_data = data;
- }
-
- if (!im.delta_compressed) {
- seed_bytes->swap(ungzipped_data);
- return StoreSeedResult::SUCCESS;
- }
-
- return ResolveDelta(ungzipped_data, seed_bytes);
-}
-
bool VariationsSeedStore::StoreSeedData(
const std::string& data,
const std::string& base64_seed_signature,
@@ -211,7 +174,7 @@ bool VariationsSeedStore::StoreSeedData(
std::string seed_bytes;
StoreSeedResult im_result =
ResolveInstanceManipulations(data, im, &seed_bytes);
- if (im_result != StoreSeedResult::SUCCESS) {
+ if (im_result != StoreSeedResult::kSuccess) {
RecordStoreSeedResult(im_result);
return false;
};
@@ -219,19 +182,19 @@ bool VariationsSeedStore::StoreSeedData(
ValidatedSeed validated;
StoreSeedResult validate_result = ValidateSeedBytes(
seed_bytes, base64_seed_signature, SeedType::LATEST, &validated);
- if (validate_result != StoreSeedResult::SUCCESS) {
+ if (validate_result != StoreSeedResult::kSuccess) {
RecordStoreSeedResult(validate_result);
if (im.delta_compressed)
- RecordStoreSeedResult(StoreSeedResult::FAILED_DELTA_STORE);
+ RecordStoreSeedResult(StoreSeedResult::kFailedDeltaStore);
return false;
}
StoreSeedResult result =
StoreValidatedSeed(validated, country_code, date_fetched);
RecordStoreSeedResult(result);
- if (result != StoreSeedResult::SUCCESS) {
+ if (result != StoreSeedResult::kSuccess) {
if (im.delta_compressed)
- RecordStoreSeedResult(StoreSeedResult::FAILED_DELTA_STORE);
+ RecordStoreSeedResult(StoreSeedResult::kFailedDeltaStore);
return false;
}
if (parsed_seed)
@@ -250,6 +213,9 @@ LoadSeedResult VariationsSeedStore::LoadSafeSeed(
if (result != LoadSeedResult::kSuccess)
return result;
+ // TODO(crbug/1261685): While it's not immediately obvious, |client_state| is
+ // not used for successfully loaded safe seeds that are rejected after
+ // additional validation (expiry and future milestone).
client_state->reference_date =
local_state_->GetTime(prefs::kVariationsSafeSeedDate);
client_state->locale =
@@ -264,88 +230,22 @@ LoadSeedResult VariationsSeedStore::LoadSafeSeed(
bool VariationsSeedStore::StoreSafeSeed(
const std::string& seed_data,
const std::string& base64_seed_signature,
+ int seed_milestone,
const ClientFilterableState& client_state,
base::Time seed_fetch_time) {
std::string base64_seed_data;
- ValidatedSeed validated;
+ ValidatedSeed seed;
StoreSeedResult validation_result = ValidateSeedBytes(
- seed_data, base64_seed_signature, SeedType::SAFE, &validated);
- if (validation_result != StoreSeedResult::SUCCESS) {
+ seed_data, base64_seed_signature, SeedType::SAFE, &seed);
+ if (validation_result != StoreSeedResult::kSuccess) {
RecordStoreSafeSeedResult(validation_result);
return false;
}
- StoreSeedResult result =
- StoreValidatedSafeSeed(validated, client_state, seed_fetch_time);
+ StoreSeedResult result = StoreValidatedSafeSeed(
+ seed, seed_milestone, client_state, seed_fetch_time);
RecordStoreSafeSeedResult(result);
- return result == StoreSeedResult::SUCCESS;
-}
-
-StoreSeedResult VariationsSeedStore::StoreValidatedSafeSeed(
- const ValidatedSeed& validated,
- const ClientFilterableState& client_state,
- base::Time seed_fetch_time) {
- std::string base64_seed_data;
- StoreSeedResult result = CompressSeedBytes(validated, &base64_seed_data);
- if (result != StoreSeedResult::SUCCESS)
- return result;
- // As a performance optimization, avoid an expensive no-op of overwriting
- // the previous safe seed with an identical copy.
- std::string previous_safe_seed =
- local_state_->GetString(prefs::kVariationsSafeCompressedSeed);
- if (base64_seed_data != previous_safe_seed) {
- // It's theoretically possible to overwrite an existing safe seed value,
- // which was identical to the latest seed, with a new value. This could
- // happen, for example, if:
- // (1) Seed A is received from the server and saved as both the safe and
- // latest seed value.
- // (2) Seed B is received from the server and saved as the latest seed
- // value.
- // (3) The user restarts Chrome, which is now running with the
- // configuration from seed B.
- // (4) Seed A is received again from the server, perhaps due to a
- // rollback.
- // In this situation, seed A should be saved as the latest seed, while
- // seed B should be saved as the safe seed, i.e. the previously saved
- // values should be swapped. Indeed, it is guaranteed that the latest seed
- // value should be overwritten in this case, as a seed should not be
- // considered safe unless a new seed can be both received *and saved* from
- // the server.
- std::string latest_seed =
- local_state_->GetString(prefs::kVariationsCompressedSeed);
- if (latest_seed == kIdenticalToSafeSeedSentinel) {
- local_state_->SetString(prefs::kVariationsCompressedSeed,
- previous_safe_seed);
- }
- local_state_->SetString(prefs::kVariationsSafeCompressedSeed,
- base64_seed_data);
- }
-
- local_state_->SetString(prefs::kVariationsSafeSeedSignature,
- validated.base64_seed_signature);
- local_state_->SetTime(prefs::kVariationsSafeSeedDate,
- client_state.reference_date);
- local_state_->SetString(prefs::kVariationsSafeSeedLocale,
- client_state.locale);
- local_state_->SetString(prefs::kVariationsSafeSeedPermanentConsistencyCountry,
- client_state.permanent_consistency_country);
- local_state_->SetString(prefs::kVariationsSafeSeedSessionConsistencyCountry,
- client_state.session_consistency_country);
-
- // As a space optimization, overwrite the stored latest seed data with an
- // alias to the safe seed, if they are identical.
- if (base64_seed_data ==
- local_state_->GetString(prefs::kVariationsCompressedSeed)) {
- local_state_->SetString(prefs::kVariationsCompressedSeed,
- kIdenticalToSafeSeedSentinel);
-
- // Moreover, in this case, the last fetch time for the safe seed should
- // match the latest seed's.
- seed_fetch_time = GetLastFetchTime();
- }
- local_state_->SetTime(prefs::kVariationsSafeSeedFetchTime, seed_fetch_time);
-
- return StoreSeedResult::SUCCESS;
+ return result == StoreSeedResult::kSuccess;
}
base::Time VariationsSeedStore::GetLastFetchTime() const {
@@ -404,9 +304,11 @@ const std::string& VariationsSeedStore::GetLatestSerialNumber() {
// static
void VariationsSeedStore::RegisterPrefs(PrefRegistrySimple* registry) {
+ // Regular seed prefs:
registry->RegisterStringPref(prefs::kVariationsCompressedSeed, std::string());
registry->RegisterStringPref(prefs::kVariationsCountry, std::string());
registry->RegisterTimePref(prefs::kVariationsLastFetchTime, base::Time());
+ registry->RegisterIntegerPref(prefs::kVariationsSeedMilestone, 0);
registry->RegisterTimePref(prefs::kVariationsSeedDate, base::Time());
registry->RegisterStringPref(prefs::kVariationsSeedSignature, std::string());
@@ -416,6 +318,7 @@ void VariationsSeedStore::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterTimePref(prefs::kVariationsSafeSeedDate, base::Time());
registry->RegisterTimePref(prefs::kVariationsSafeSeedFetchTime, base::Time());
registry->RegisterStringPref(prefs::kVariationsSafeSeedLocale, std::string());
+ registry->RegisterIntegerPref(prefs::kVariationsSafeSeedMilestone, 0);
registry->RegisterStringPref(
prefs::kVariationsSafeSeedPermanentConsistencyCountry, std::string());
registry->RegisterStringPref(
@@ -431,6 +334,17 @@ VerifySignatureResult VariationsSeedStore::VerifySeedSignatureForTesting(
return VerifySeedSignature(seed_bytes, base64_seed_signature);
}
+// It is intentional that country-related prefs are retained for regular seeds
+// and cleared for safe seeds.
+//
+// For regular seeds, the prefs are kept for two reasons. First, it's better to
+// have some idea of a country recently associated with the device. Second, some
+// past, country-gated launches started relying on the VariationsService-
+// provided country when they retired server-side configs.
+//
+// The safe seed prefs are needed to correctly apply a safe seed, so if the safe
+// seed is cleared, there's no reason to retain them as they may be incorrect
+// for the next safe seed.
void VariationsSeedStore::ClearPrefs(SeedType seed_type) {
if (seed_type == SeedType::LATEST) {
local_state_->ClearPref(prefs::kVariationsCompressedSeed);
@@ -445,6 +359,7 @@ void VariationsSeedStore::ClearPrefs(SeedType seed_type) {
local_state_->ClearPref(prefs::kVariationsSafeSeedDate);
local_state_->ClearPref(prefs::kVariationsSafeSeedFetchTime);
local_state_->ClearPref(prefs::kVariationsSafeSeedLocale);
+ local_state_->ClearPref(prefs::kVariationsSafeSeedMilestone);
local_state_->ClearPref(
prefs::kVariationsSafeSeedPermanentConsistencyCountry);
local_state_->ClearPref(prefs::kVariationsSafeSeedSessionConsistencyCountry);
@@ -556,41 +471,41 @@ LoadSeedResult VariationsSeedStore::ReadSeedData(SeedType seed_type,
return LoadSeedResult::kSuccess;
}
-StoreSeedResult VariationsSeedStore::StoreValidatedSeed(
- const ValidatedSeed& validated,
- const std::string& country_code,
- const base::Time& date_fetched) {
- std::string base64_seed_data;
- StoreSeedResult result = CompressSeedBytes(validated, &base64_seed_data);
- if (result != StoreSeedResult::SUCCESS)
- return result;
-#if defined(OS_ANDROID)
- // If currently we do not have any stored pref then we mark seed storing as
- // successful on the Java side to avoid repeated seed fetches.
- if (local_state_->GetString(prefs::kVariationsCompressedSeed).empty() &&
- use_first_run_prefs_) {
- android::MarkVariationsSeedAsStored();
- }
-#endif
+StoreSeedResult VariationsSeedStore::ResolveDelta(
+ const std::string& delta_bytes,
+ std::string* seed_bytes) {
+ DCHECK(seed_bytes);
+ std::string existing_seed_bytes;
+ LoadSeedResult read_result =
+ ReadSeedData(SeedType::LATEST, &existing_seed_bytes);
+ if (read_result != LoadSeedResult::kSuccess)
+ return StoreSeedResult::kFailedDeltaReadSeed;
+ if (!ApplyDeltaPatch(existing_seed_bytes, delta_bytes, seed_bytes))
+ return StoreSeedResult::kFailedDeltaApply;
+ return StoreSeedResult::kSuccess;
+}
- // Update the saved country code only if one was returned from the server.
- if (!country_code.empty())
- local_state_->SetString(prefs::kVariationsCountry, country_code);
+StoreSeedResult VariationsSeedStore::ResolveInstanceManipulations(
+ const std::string& data,
+ const InstanceManipulations& im,
+ std::string* seed_bytes) {
+ DCHECK(seed_bytes);
+ // If the data is gzip compressed, first uncompress it.
+ std::string ungzipped_data;
+ if (im.gzip_compressed) {
+ StoreSeedResult result = Uncompress(data, &ungzipped_data);
+ if (result != StoreSeedResult::kSuccess)
+ return result;
+ } else {
+ ungzipped_data = data;
+ }
- // As a space optimization, store an alias to the safe seed if the contents
- // are identical.
- bool matches_safe_seed =
- (base64_seed_data ==
- local_state_->GetString(prefs::kVariationsSafeCompressedSeed));
- local_state_->SetString(
- prefs::kVariationsCompressedSeed,
- matches_safe_seed ? kIdenticalToSafeSeedSentinel : base64_seed_data);
+ if (!im.delta_compressed) {
+ seed_bytes->swap(ungzipped_data);
+ return StoreSeedResult::kSuccess;
+ }
- UpdateSeedDateAndLogDayChange(date_fetched);
- local_state_->SetString(prefs::kVariationsSeedSignature,
- validated.base64_seed_signature);
- latest_serial_number_ = validated.parsed.serial_number();
- return StoreSeedResult::SUCCESS;
+ return ResolveDelta(ungzipped_data, seed_bytes);
}
StoreSeedResult VariationsSeedStore::ValidateSeedBytes(
@@ -600,12 +515,12 @@ StoreSeedResult VariationsSeedStore::ValidateSeedBytes(
ValidatedSeed* result) {
DCHECK(result);
if (seed_bytes.empty())
- return StoreSeedResult::FAILED_EMPTY_GZIP_CONTENTS;
+ return StoreSeedResult::kFailedEmptyGzipContents;
// Only store the seed data if it parses correctly.
VariationsSeed seed;
if (!seed.ParseFromString(seed_bytes))
- return StoreSeedResult::FAILED_PARSE;
+ return StoreSeedResult::kFailedParse;
if (signature_verification_enabled_) {
const VerifySignatureResult verify_result =
@@ -624,12 +539,12 @@ StoreSeedResult VariationsSeedStore::ValidateSeedBytes(
}
if (verify_result != VerifySignatureResult::VALID_SIGNATURE)
- return StoreSeedResult::FAILED_SIGNATURE;
+ return StoreSeedResult::kFailedSignature;
}
result->bytes = seed_bytes;
result->base64_seed_signature = base64_seed_signature;
result->parsed.Swap(&seed);
- return StoreSeedResult::SUCCESS;
+ return StoreSeedResult::kSuccess;
}
StoreSeedResult VariationsSeedStore::CompressSeedBytes(
@@ -638,10 +553,120 @@ StoreSeedResult VariationsSeedStore::CompressSeedBytes(
// Compress the seed before base64-encoding and storing.
std::string compressed_seed_data;
if (!compression::GzipCompress(seed.bytes, &compressed_seed_data))
- return StoreSeedResult::FAILED_GZIP;
+ return StoreSeedResult::kFailedGzip;
base::Base64Encode(compressed_seed_data, base64_seed_data);
- return StoreSeedResult::SUCCESS;
+ return StoreSeedResult::kSuccess;
+}
+
+StoreSeedResult VariationsSeedStore::StoreValidatedSeed(
+ const ValidatedSeed& seed,
+ const std::string& country_code,
+ const base::Time& date_fetched) {
+ std::string base64_seed_data;
+ StoreSeedResult result = CompressSeedBytes(seed, &base64_seed_data);
+ if (result != StoreSeedResult::kSuccess)
+ return result;
+#if defined(OS_ANDROID)
+ // If currently we do not have any stored pref then we mark seed storing as
+ // successful on the Java side to avoid repeated seed fetches.
+ if (local_state_->GetString(prefs::kVariationsCompressedSeed).empty() &&
+ use_first_run_prefs_) {
+ android::MarkVariationsSeedAsStored();
+ }
+#endif
+
+ // Update the saved country code only if one was returned from the server.
+ if (!country_code.empty())
+ local_state_->SetString(prefs::kVariationsCountry, country_code);
+
+ int milestone;
+ if (base::StringToInt(version_info::GetMajorVersionNumber(), &milestone))
+ local_state_->SetInteger(prefs::kVariationsSeedMilestone, milestone);
+
+ // As a space optimization, store an alias to the safe seed if the contents
+ // are identical.
+ bool matches_safe_seed =
+ (base64_seed_data ==
+ local_state_->GetString(prefs::kVariationsSafeCompressedSeed));
+ local_state_->SetString(
+ prefs::kVariationsCompressedSeed,
+ matches_safe_seed ? kIdenticalToSafeSeedSentinel : base64_seed_data);
+
+ UpdateSeedDateAndLogDayChange(date_fetched);
+ local_state_->SetString(prefs::kVariationsSeedSignature,
+ seed.base64_seed_signature);
+ latest_serial_number_ = seed.parsed.serial_number();
+ return StoreSeedResult::kSuccess;
+}
+
+StoreSeedResult VariationsSeedStore::StoreValidatedSafeSeed(
+ const ValidatedSeed& seed,
+ int seed_milestone,
+ const ClientFilterableState& client_state,
+ base::Time seed_fetch_time) {
+ std::string base64_seed_data;
+ StoreSeedResult result = CompressSeedBytes(seed, &base64_seed_data);
+ if (result != StoreSeedResult::kSuccess)
+ return result;
+ // As a performance optimization, avoid an expensive no-op of overwriting
+ // the previous safe seed with an identical copy.
+ std::string previous_safe_seed =
+ local_state_->GetString(prefs::kVariationsSafeCompressedSeed);
+ if (base64_seed_data != previous_safe_seed) {
+ // It's theoretically possible to overwrite an existing safe seed value,
+ // which was identical to the latest seed, with a new value. This could
+ // happen, for example, if:
+ // (1) Seed A is received from the server and saved as both the safe and
+ // latest seed value.
+ // (2) Seed B is received from the server and saved as the latest seed
+ // value.
+ // (3) The user restarts Chrome, which is now running with the
+ // configuration from seed B.
+ // (4) Seed A is received again from the server, perhaps due to a
+ // rollback.
+ // In this situation, seed A should be saved as the latest seed, while
+ // seed B should be saved as the safe seed, i.e. the previously saved
+ // values should be swapped. Indeed, it is guaranteed that the latest seed
+ // value should be overwritten in this case, as a seed should not be
+ // considered safe unless a new seed can be both received *and saved* from
+ // the server.
+ std::string latest_seed =
+ local_state_->GetString(prefs::kVariationsCompressedSeed);
+ if (latest_seed == kIdenticalToSafeSeedSentinel) {
+ local_state_->SetString(prefs::kVariationsCompressedSeed,
+ previous_safe_seed);
+ }
+ local_state_->SetString(prefs::kVariationsSafeCompressedSeed,
+ base64_seed_data);
+ }
+
+ local_state_->SetString(prefs::kVariationsSafeSeedSignature,
+ seed.base64_seed_signature);
+ local_state_->SetTime(prefs::kVariationsSafeSeedDate,
+ client_state.reference_date);
+ local_state_->SetString(prefs::kVariationsSafeSeedLocale,
+ client_state.locale);
+ local_state_->SetInteger(prefs::kVariationsSafeSeedMilestone, seed_milestone);
+ local_state_->SetString(prefs::kVariationsSafeSeedPermanentConsistencyCountry,
+ client_state.permanent_consistency_country);
+ local_state_->SetString(prefs::kVariationsSafeSeedSessionConsistencyCountry,
+ client_state.session_consistency_country);
+
+ // As a space optimization, overwrite the stored latest seed data with an
+ // alias to the safe seed, if they are identical.
+ if (base64_seed_data ==
+ local_state_->GetString(prefs::kVariationsCompressedSeed)) {
+ local_state_->SetString(prefs::kVariationsCompressedSeed,
+ kIdenticalToSafeSeedSentinel);
+
+ // Moreover, in this case, the last fetch time for the safe seed should
+ // match the latest seed's.
+ seed_fetch_time = GetLastFetchTime();
+ }
+ local_state_->SetTime(prefs::kVariationsSafeSeedFetchTime, seed_fetch_time);
+
+ return StoreSeedResult::kSuccess;
}
// static
diff --git a/chromium/components/variations/variations_seed_store.h b/chromium/components/variations/variations_seed_store.h
index 7dfa9d519ec..bc0f40c9b65 100644
--- a/chromium/components/variations/variations_seed_store.h
+++ b/chromium/components/variations/variations_seed_store.h
@@ -12,7 +12,7 @@
#include "base/compiler_specific.h"
#include "base/component_export.h"
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
+#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/variations/metrics.h"
@@ -110,6 +110,7 @@ class COMPONENT_EXPORT(VARIATIONS) VariationsSeedStore {
// Virtual for testing.
virtual bool StoreSafeSeed(const std::string& seed_data,
const std::string& base64_seed_signature,
+ int seed_milestone,
const ClientFilterableState& client_state,
base::Time seed_fetch_time);
@@ -232,7 +233,8 @@ class COMPONENT_EXPORT(VARIATIONS) VariationsSeedStore {
// Updates the safe seed with validated data.
StoreSeedResult StoreValidatedSafeSeed(
- const ValidatedSeed& validated,
+ const ValidatedSeed& seed,
+ int seed_milestone,
const ClientFilterableState& client_state,
base::Time seed_fetch_time) WARN_UNUSED_RESULT;
@@ -243,7 +245,7 @@ class COMPONENT_EXPORT(VARIATIONS) VariationsSeedStore {
std::string* output) WARN_UNUSED_RESULT;
// The pref service used to persist the variations seed.
- PrefService* local_state_;
+ raw_ptr<PrefService> local_state_;
// Cached serial number from the most recently fetched variations seed.
std::string latest_serial_number_;
diff --git a/chromium/components/variations/variations_seed_store_unittest.cc b/chromium/components/variations/variations_seed_store_unittest.cc
index 1b311378d5e..c139844609f 100644
--- a/chromium/components/variations/variations_seed_store_unittest.cc
+++ b/chromium/components/variations/variations_seed_store_unittest.cc
@@ -9,7 +9,6 @@
#include "base/base64.h"
#include "base/callback_helpers.h"
-#include "base/macros.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/time/time.h"
#include "base/version.h"
@@ -38,6 +37,10 @@ namespace {
// if the constant used internally in the implementation changes.
constexpr char kIdenticalToSafeSeedSentinel[] = "safe_seed_content";
+// TODO(crbug/1205645): Consider consolidating TestVariationsSeedStore and
+// SignatureVerifyingVariationsSeedStore. Outside of tests, signature
+// verification is enabled although prior to crrev.com/c/2181564, signature
+// verification was not done on iOS or Android.
class TestVariationsSeedStore : public VariationsSeedStore {
public:
explicit TestVariationsSeedStore(
@@ -60,9 +63,6 @@ class TestVariationsSeedStore : public VariationsSeedStore {
}
};
-// Signature verification is disabled on Android and iOS for performance
-// reasons. This class re-enables it for tests, which don't mind the (small)
-// performance penalty.
class SignatureVerifyingVariationsSeedStore : public VariationsSeedStore {
public:
explicit SignatureVerifyingVariationsSeedStore(PrefService* local_state)
@@ -158,6 +158,7 @@ void SetAllSeedPrefsToNonDefaultValues(PrefService* prefs) {
prefs->SetTime(prefs::kVariationsSafeSeedDate, now - delta * 2);
prefs->SetTime(prefs::kVariationsSafeSeedFetchTime, now - delta * 3);
prefs->SetString(prefs::kVariationsSafeSeedLocale, "en-MX");
+ prefs->SetInteger(prefs::kVariationsSafeSeedMilestone, 90);
prefs->SetString(prefs::kVariationsSafeSeedPermanentConsistencyCountry, "mx");
prefs->SetString(prefs::kVariationsSafeSeedSessionConsistencyCountry, "gt");
prefs->SetString(prefs::kVariationsSafeSeedSignature, "mustard");
@@ -189,6 +190,7 @@ void CheckSafeSeedPrefsAreSet(const TestingPrefServiceSimple& prefs) {
EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedDate));
EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedFetchTime));
EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedLocale));
+ EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedMilestone));
EXPECT_FALSE(PrefHasDefaultValue(
prefs, prefs::kVariationsSafeSeedPermanentConsistencyCountry));
EXPECT_FALSE(PrefHasDefaultValue(
@@ -201,6 +203,7 @@ void CheckSafeSeedPrefsAreCleared(const TestingPrefServiceSimple& prefs) {
EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedDate));
EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedFetchTime));
EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedLocale));
+ EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedMilestone));
EXPECT_TRUE(PrefHasDefaultValue(
prefs, prefs::kVariationsSafeSeedPermanentConsistencyCountry));
EXPECT_TRUE(PrefHasDefaultValue(
@@ -210,6 +213,17 @@ void CheckSafeSeedPrefsAreCleared(const TestingPrefServiceSimple& prefs) {
} // namespace
+struct InvalidSafeSeedTestParams {
+ const std::string test_name;
+ const std::string seed;
+ const std::string signature;
+ StoreSeedResult store_seed_result;
+ absl::optional<VerifySignatureResult> verify_signature_result = absl::nullopt;
+};
+
+using StoreInvalidSafeSeedTest =
+ ::testing::TestWithParam<InvalidSafeSeedTestParams>;
+
TEST(VariationsSeedStoreTest, LoadSeed_ValidSeed) {
// Store good seed data to test if loading from prefs works.
const VariationsSeed seed = CreateTestSeed();
@@ -600,229 +614,169 @@ TEST(VariationsSeedStoreTest, LoadSafeSeed_EmptySeed) {
LoadSeedResult::kEmpty, 1);
}
-TEST(VariationsSeedStoreTest, StoreSafeSeed_ValidSeed) {
- const VariationsSeed seed = CreateTestSeed();
- const std::string serialized_seed = SerializeSeed(seed);
- const std::string signature = "a completely ignored signature";
- ClientFilterableState client_state(base::BindOnce([] { return false; }));
- client_state.locale = "en-US";
- client_state.reference_date = WrapTime(12345);
- client_state.session_consistency_country = "US";
- client_state.permanent_consistency_country = "CA";
- const base::Time fetch_time = WrapTime(99999);
-
+INSTANTIATE_TEST_SUITE_P(
+ All,
+ StoreInvalidSafeSeedTest,
+ ::testing::Values(
+ InvalidSafeSeedTestParams{
+ .test_name = "EmptySeed",
+ .seed = "",
+ .signature = "unused signature",
+ .store_seed_result = StoreSeedResult::kFailedEmptyGzipContents},
+ InvalidSafeSeedTestParams{
+ .test_name = "InvalidSeed",
+ .seed = "invalid seed",
+ .signature = "unused signature",
+ .store_seed_result = StoreSeedResult::kFailedParse},
+ InvalidSafeSeedTestParams{
+ .test_name = "InvalidSignature",
+ .seed = SerializeSeed(CreateTestSeed()),
+ // A well-formed signature that does not correspond to the seed.
+ .signature = kTestSeedData.base64_signature,
+ .store_seed_result = StoreSeedResult::kFailedSignature,
+ .verify_signature_result = VerifySignatureResult::INVALID_SEED}),
+ [](const ::testing::TestParamInfo<InvalidSafeSeedTestParams>& params) {
+ return params.param.test_name;
+ });
+
+// Verify that attempting to store an invalid safe seed fails and does not
+// modify Local State's existing safe-seed-related prefs.
+TEST_P(StoreInvalidSafeSeedTest, StoreSafeSeed) {
TestingPrefServiceSimple prefs;
VariationsSeedStore::RegisterPrefs(prefs.registry());
- TestVariationsSeedStore seed_store(&prefs);
- base::HistogramTester histogram_tester;
- EXPECT_TRUE(seed_store.StoreSafeSeed(serialized_seed, signature, client_state,
- fetch_time));
+ // Set a safe seed and its associated prefs to their expected values. Also,
+ // specify different safe seed pref values that are later attempted to be
+ // stored.
+ const std::string expected_seed = "a seed";
+ InvalidSafeSeedTestParams params = GetParam();
+ const std::string seed_to_store = params.seed;
+ prefs.SetString(prefs::kVariationsSafeCompressedSeed, expected_seed);
- // Verify the stored data.
- std::string loaded_compressed_seed =
- prefs.GetString(prefs::kVariationsSafeCompressedSeed);
- std::string decoded_compressed_seed;
- ASSERT_TRUE(
- base::Base64Decode(loaded_compressed_seed, &decoded_compressed_seed));
- EXPECT_EQ(Compress(serialized_seed), decoded_compressed_seed);
- EXPECT_EQ(signature, prefs.GetString(prefs::kVariationsSafeSeedSignature));
- EXPECT_EQ("en-US", prefs.GetString(prefs::kVariationsSafeSeedLocale));
- EXPECT_EQ(WrapTime(12345), prefs.GetTime(prefs::kVariationsSafeSeedDate));
- EXPECT_EQ(WrapTime(99999),
- prefs.GetTime(prefs::kVariationsSafeSeedFetchTime));
- EXPECT_EQ("US", prefs.GetString(
- prefs::kVariationsSafeSeedSessionConsistencyCountry));
- EXPECT_EQ("CA", prefs.GetString(
- prefs::kVariationsSafeSeedPermanentConsistencyCountry));
+ const std::string expected_signature = "a signature";
+ const std::string signature_to_store = params.signature;
+ prefs.SetString(prefs::kVariationsSafeSeedSignature, expected_signature);
- // Verify metrics.
- histogram_tester.ExpectUniqueSample(
- "Variations.SafeMode.StoreSafeSeed.Result", StoreSeedResult::SUCCESS, 1);
-}
+ const int expected_milestone = 90;
+ const int milestone_to_store = 91;
+ prefs.SetInteger(prefs::kVariationsSafeSeedMilestone, expected_milestone);
-TEST(VariationsSeedStoreTest, StoreSafeSeed_EmptySeed) {
- const std::string serialized_seed;
- const std::string signature = "a completely ignored signature";
- ClientFilterableState client_state(base::BindOnce([] { return false; }));
- client_state.locale = "en-US";
- client_state.reference_date = WrapTime(54321);
- client_state.session_consistency_country = "US";
- client_state.permanent_consistency_country = "CA";
- base::Time fetch_time = WrapTime(99999);
-
- TestingPrefServiceSimple prefs;
- VariationsSeedStore::RegisterPrefs(prefs.registry());
- prefs.SetString(prefs::kVariationsSafeCompressedSeed, "a seed");
- prefs.SetString(prefs::kVariationsSafeSeedSignature, "a signature");
- prefs.SetString(prefs::kVariationsSafeSeedLocale, "en-US");
- prefs.SetString(prefs::kVariationsSafeSeedPermanentConsistencyCountry, "CA");
- prefs.SetString(prefs::kVariationsSafeSeedSessionConsistencyCountry, "US");
- prefs.SetTime(prefs::kVariationsSafeSeedDate, WrapTime(12345));
- prefs.SetTime(prefs::kVariationsSafeSeedFetchTime, WrapTime(34567));
-
- TestVariationsSeedStore seed_store(&prefs);
-
- base::HistogramTester histogram_tester;
- EXPECT_FALSE(seed_store.StoreSafeSeed(serialized_seed, signature,
- client_state, fetch_time));
-
- // Verify that none of the prefs were overwritten.
- EXPECT_EQ("a seed", prefs.GetString(prefs::kVariationsSafeCompressedSeed));
- EXPECT_EQ("a signature",
- prefs.GetString(prefs::kVariationsSafeSeedSignature));
- EXPECT_EQ("en-US", prefs.GetString(prefs::kVariationsSafeSeedLocale));
- EXPECT_EQ("CA", prefs.GetString(
- prefs::kVariationsSafeSeedPermanentConsistencyCountry));
- EXPECT_EQ("US", prefs.GetString(
- prefs::kVariationsSafeSeedSessionConsistencyCountry));
- EXPECT_EQ(WrapTime(12345), prefs.GetTime(prefs::kVariationsSafeSeedDate));
- EXPECT_EQ(WrapTime(34567),
- prefs.GetTime(prefs::kVariationsSafeSeedFetchTime));
-
- // Verify metrics.
- histogram_tester.ExpectUniqueSample(
- "Variations.SafeMode.StoreSafeSeed.Result",
- StoreSeedResult::FAILED_EMPTY_GZIP_CONTENTS, 1);
-}
+ const base::Time now = base::Time::Now();
+ const base::Time expected_fetch_time = now - base::Hours(3);
+ const base::Time fetch_time_to_store = now - base::Hours(1);
+ prefs.SetTime(prefs::kVariationsSafeSeedFetchTime, expected_fetch_time);
-TEST(VariationsSeedStoreTest, StoreSafeSeed_InvalidSeed) {
- const std::string serialized_seed = "a nonsense seed";
- const std::string signature = "a completely ignored signature";
ClientFilterableState client_state(base::BindOnce([] { return false; }));
- client_state.locale = "en-US";
- client_state.reference_date = WrapTime(12345);
- client_state.session_consistency_country = "US";
- client_state.permanent_consistency_country = "CA";
- base::Time fetch_time = WrapTime(54321);
- TestingPrefServiceSimple prefs;
- VariationsSeedStore::RegisterPrefs(prefs.registry());
- prefs.SetString(prefs::kVariationsSafeCompressedSeed, "a previous seed");
- prefs.SetString(prefs::kVariationsSafeSeedSignature, "a previous signature");
- prefs.SetString(prefs::kVariationsSafeSeedLocale, "en-CA");
- prefs.SetString(prefs::kVariationsSafeSeedPermanentConsistencyCountry, "IN");
- prefs.SetString(prefs::kVariationsSafeSeedSessionConsistencyCountry, "MX");
- prefs.SetTime(prefs::kVariationsSafeSeedDate, WrapTime(67890));
- prefs.SetTime(prefs::kVariationsSafeSeedFetchTime, WrapTime(13579));
-
- SignatureVerifyingVariationsSeedStore seed_store(&prefs);
-
- base::HistogramTester histogram_tester;
- EXPECT_FALSE(seed_store.StoreSafeSeed(serialized_seed, signature,
- client_state, fetch_time));
+ const std::string expected_locale = "en-US";
+ client_state.locale = "pt-PT";
+ prefs.SetString(prefs::kVariationsSafeSeedLocale, expected_locale);
- // Verify that none of the prefs were overwritten.
- EXPECT_EQ("a previous seed",
- prefs.GetString(prefs::kVariationsSafeCompressedSeed));
- EXPECT_EQ("a previous signature",
- prefs.GetString(prefs::kVariationsSafeSeedSignature));
- EXPECT_EQ("en-CA", prefs.GetString(prefs::kVariationsSafeSeedLocale));
- EXPECT_EQ("IN", prefs.GetString(
- prefs::kVariationsSafeSeedPermanentConsistencyCountry));
- EXPECT_EQ("MX", prefs.GetString(
- prefs::kVariationsSafeSeedSessionConsistencyCountry));
- EXPECT_EQ(WrapTime(67890), prefs.GetTime(prefs::kVariationsSafeSeedDate));
- EXPECT_EQ(WrapTime(13579),
- prefs.GetTime(prefs::kVariationsSafeSeedFetchTime));
-
- // Verify metrics.
- histogram_tester.ExpectUniqueSample(
- "Variations.SafeMode.StoreSafeSeed.Result", StoreSeedResult::FAILED_PARSE,
- 1);
-}
-
-TEST(VariationsSeedStoreTest, StoreSafeSeed_InvalidSignature) {
- const VariationsSeed seed = CreateTestSeed();
- const std::string serialized_seed = SerializeSeed(seed);
- // A valid signature, but for a different seed.
- const std::string signature = kTestSeedData.base64_signature;
- ClientFilterableState client_state(base::BindOnce([] { return false; }));
- client_state.locale = "en-US";
- client_state.reference_date = WrapTime(12345);
- client_state.session_consistency_country = "US";
+ const std::string expected_permanent_consistency_country = "US";
client_state.permanent_consistency_country = "CA";
- const base::Time fetch_time = WrapTime(34567);
+ prefs.SetString(prefs::kVariationsSafeSeedPermanentConsistencyCountry,
+ expected_permanent_consistency_country);
- TestingPrefServiceSimple prefs;
- VariationsSeedStore::RegisterPrefs(prefs.registry());
- prefs.SetString(prefs::kVariationsSafeCompressedSeed, "a previous seed");
- prefs.SetString(prefs::kVariationsSafeSeedSignature, "a previous signature");
- prefs.SetString(prefs::kVariationsSafeSeedLocale, "en-CA");
- prefs.SetString(prefs::kVariationsSafeSeedPermanentConsistencyCountry, "IN");
- prefs.SetString(prefs::kVariationsSafeSeedSessionConsistencyCountry, "MX");
- prefs.SetTime(prefs::kVariationsSafeSeedDate, WrapTime(67890));
- prefs.SetTime(prefs::kVariationsSafeSeedFetchTime, WrapTime(24680));
+ const std::string expected_session_consistency_country = "BR";
+ client_state.session_consistency_country = "PT";
+ prefs.SetString(prefs::kVariationsSafeSeedSessionConsistencyCountry,
+ expected_session_consistency_country);
- SignatureVerifyingVariationsSeedStore seed_store(&prefs);
+ const base::Time expected_date = now - base::Days(2);
+ client_state.reference_date = now - base::Days(1);
+ prefs.SetTime(prefs::kVariationsSafeSeedDate, expected_date);
+ SignatureVerifyingVariationsSeedStore seed_store(&prefs);
base::HistogramTester histogram_tester;
- EXPECT_FALSE(seed_store.StoreSafeSeed(serialized_seed, signature,
- client_state, fetch_time));
- // Verify that none of the prefs were overwritten.
- EXPECT_EQ("a previous seed",
- prefs.GetString(prefs::kVariationsSafeCompressedSeed));
- EXPECT_EQ("a previous signature",
- prefs.GetString(prefs::kVariationsSafeSeedSignature));
- EXPECT_EQ("en-CA", prefs.GetString(prefs::kVariationsSafeSeedLocale));
- EXPECT_EQ("IN", prefs.GetString(
- prefs::kVariationsSafeSeedPermanentConsistencyCountry));
- EXPECT_EQ("MX", prefs.GetString(
- prefs::kVariationsSafeSeedSessionConsistencyCountry));
- EXPECT_EQ(WrapTime(67890), prefs.GetTime(prefs::kVariationsSafeSeedDate));
- EXPECT_EQ(WrapTime(24680),
- prefs.GetTime(prefs::kVariationsSafeSeedFetchTime));
+ // Verify that attempting to store an invalid seed fails.
+ EXPECT_FALSE(seed_store.StoreSafeSeed(seed_to_store, signature_to_store,
+ milestone_to_store, client_state,
+ fetch_time_to_store));
+
+ // Verify that none of the safe seed prefs were overwritten.
+ EXPECT_EQ(prefs.GetString(prefs::kVariationsSafeCompressedSeed),
+ expected_seed);
+ EXPECT_EQ(prefs.GetString(prefs::kVariationsSafeSeedSignature),
+ expected_signature);
+ EXPECT_EQ(prefs.GetString(prefs::kVariationsSafeSeedLocale), expected_locale);
+ EXPECT_EQ(prefs.GetInteger(prefs::kVariationsSafeSeedMilestone),
+ expected_milestone);
+ EXPECT_EQ(
+ prefs.GetString(prefs::kVariationsSafeSeedPermanentConsistencyCountry),
+ expected_permanent_consistency_country);
+ EXPECT_EQ(
+ prefs.GetString(prefs::kVariationsSafeSeedSessionConsistencyCountry),
+ expected_session_consistency_country);
+ EXPECT_EQ(prefs.GetTime(prefs::kVariationsSafeSeedDate), expected_date);
+ EXPECT_EQ(prefs.GetTime(prefs::kVariationsSafeSeedFetchTime),
+ expected_fetch_time);
// Verify metrics.
histogram_tester.ExpectUniqueSample(
- "Variations.SafeMode.StoreSafeSeed.Result",
- StoreSeedResult::FAILED_SIGNATURE, 1);
- histogram_tester.ExpectUniqueSample(
- "Variations.SafeMode.StoreSafeSeed.SignatureValidity",
- VerifySignatureResult::INVALID_SEED, 1);
+ "Variations.SafeMode.StoreSafeSeed.Result", params.store_seed_result, 1);
+ if (params.verify_signature_result.has_value()) {
+ histogram_tester.ExpectUniqueSample(
+ "Variations.SafeMode.StoreSafeSeed.SignatureValidity",
+ params.verify_signature_result.value(), 1);
+ }
}
TEST(VariationsSeedStoreTest, StoreSafeSeed_ValidSignature) {
- std::string serialized_seed;
+ std::string expected_seed;
ASSERT_TRUE(base::Base64Decode(kTestSeedData.base64_uncompressed_data,
- &serialized_seed));
- const std::string signature = kTestSeedData.base64_signature;
+ &expected_seed));
+ const std::string expected_signature = kTestSeedData.base64_signature;
+ const int expected_seed_milestone = 92;
+
ClientFilterableState client_state(base::BindOnce([] { return false; }));
- client_state.locale = "en-US";
- client_state.reference_date = WrapTime(12345);
- client_state.session_consistency_country = "US";
- client_state.permanent_consistency_country = "CA";
- const base::Time fetch_time = WrapTime(34567);
+ const std::string expected_locale = "en-US";
+ client_state.locale = expected_locale;
+ const base::Time now = base::Time::Now();
+ const base::Time expected_date = now - base::Days(1);
+ client_state.reference_date = expected_date;
+ const std::string expected_permanent_consistency_country = "US";
+ client_state.permanent_consistency_country =
+ expected_permanent_consistency_country;
+ const std::string expected_session_consistency_country = "CA";
+ client_state.session_consistency_country =
+ expected_session_consistency_country;
+ const base::Time expected_fetch_time = now - base::Hours(6);
TestingPrefServiceSimple prefs;
VariationsSeedStore::RegisterPrefs(prefs.registry());
SignatureVerifyingVariationsSeedStore seed_store(&prefs);
-
base::HistogramTester histogram_tester;
- EXPECT_TRUE(seed_store.StoreSafeSeed(serialized_seed, signature, client_state,
- fetch_time));
- // Verify the stored data.
- std::string loaded_compressed_seed =
+ // Verify that storing the safe seed succeeded.
+ EXPECT_TRUE(seed_store.StoreSafeSeed(expected_seed, expected_signature,
+ expected_seed_milestone, client_state,
+ expected_fetch_time));
+
+ // Verify that safe-seed-related prefs were successfully stored.
+ const std::string safe_seed =
prefs.GetString(prefs::kVariationsSafeCompressedSeed);
std::string decoded_compressed_seed;
- ASSERT_TRUE(
- base::Base64Decode(loaded_compressed_seed, &decoded_compressed_seed));
- EXPECT_EQ(Compress(serialized_seed), decoded_compressed_seed);
- EXPECT_EQ(signature, prefs.GetString(prefs::kVariationsSafeSeedSignature));
- EXPECT_EQ("en-US", prefs.GetString(prefs::kVariationsSafeSeedLocale));
- EXPECT_EQ(WrapTime(12345), prefs.GetTime(prefs::kVariationsSafeSeedDate));
- EXPECT_EQ(WrapTime(34567),
- prefs.GetTime(prefs::kVariationsSafeSeedFetchTime));
- EXPECT_EQ("US", prefs.GetString(
- prefs::kVariationsSafeSeedSessionConsistencyCountry));
- EXPECT_EQ("CA", prefs.GetString(
- prefs::kVariationsSafeSeedPermanentConsistencyCountry));
+ ASSERT_TRUE(base::Base64Decode(safe_seed, &decoded_compressed_seed));
+ EXPECT_EQ(Compress(expected_seed), decoded_compressed_seed);
+ EXPECT_EQ(prefs.GetString(prefs::kVariationsSafeSeedSignature),
+ expected_signature);
+ EXPECT_EQ(prefs.GetString(prefs::kVariationsSafeSeedLocale), expected_locale);
+ EXPECT_EQ(prefs.GetInteger(prefs::kVariationsSafeSeedMilestone),
+ expected_seed_milestone);
+ EXPECT_EQ(
+ prefs.GetString(prefs::kVariationsSafeSeedPermanentConsistencyCountry),
+ expected_permanent_consistency_country);
+ EXPECT_EQ(
+ prefs.GetString(prefs::kVariationsSafeSeedSessionConsistencyCountry),
+ expected_session_consistency_country);
+ EXPECT_EQ(prefs.GetTime(prefs::kVariationsSafeSeedDate), expected_date);
+ EXPECT_EQ(prefs.GetTime(prefs::kVariationsSafeSeedFetchTime),
+ expected_fetch_time);
// Verify metrics.
histogram_tester.ExpectUniqueSample(
- "Variations.SafeMode.StoreSafeSeed.Result", StoreSeedResult::SUCCESS, 1);
+ "Variations.SafeMode.StoreSafeSeed.Result", StoreSeedResult::kSuccess, 1);
histogram_tester.ExpectUniqueSample(
"Variations.SafeMode.StoreSafeSeed.SignatureValidity",
VerifySignatureResult::VALID_SIGNATURE, 1);
@@ -835,6 +789,7 @@ TEST(VariationsSeedStoreTest, StoreSafeSeed_IdenticalToLatestSeed) {
const std::string signature = "a completely ignored signature";
ClientFilterableState unused_client_state(
base::BindOnce([] { return false; }));
+ const int unused_seed_milestone = 92;
const base::Time safe_seed_fetch_time = WrapTime(12345);
TestingPrefServiceSimple prefs;
@@ -846,7 +801,8 @@ TEST(VariationsSeedStoreTest, StoreSafeSeed_IdenticalToLatestSeed) {
TestVariationsSeedStore seed_store(&prefs);
base::HistogramTester histogram_tester;
EXPECT_TRUE(seed_store.StoreSafeSeed(
- serialized_seed, signature, unused_client_state, safe_seed_fetch_time));
+ serialized_seed, signature, unused_seed_milestone, unused_client_state,
+ safe_seed_fetch_time));
// Verify the latest seed value was migrated to a sentinel value, rather than
// the full string.
@@ -874,7 +830,7 @@ TEST(VariationsSeedStoreTest, StoreSafeSeed_IdenticalToLatestSeed) {
// Verify metrics.
histogram_tester.ExpectUniqueSample(
- "Variations.SafeMode.StoreSafeSeed.Result", StoreSeedResult::SUCCESS, 1);
+ "Variations.SafeMode.StoreSafeSeed.Result", StoreSeedResult::kSuccess, 1);
}
TEST(VariationsSeedStoreTest, StoreSafeSeed_PreviouslyIdenticalToLatestSeed) {
@@ -894,6 +850,7 @@ TEST(VariationsSeedStoreTest, StoreSafeSeed_PreviouslyIdenticalToLatestSeed) {
const base::Time fetch_time = WrapTime(12345);
ClientFilterableState unused_client_state(
base::BindOnce([] { return false; }));
+ const int unused_seed_milestone = 92;
TestingPrefServiceSimple prefs;
VariationsSeedStore::RegisterPrefs(prefs.registry());
@@ -904,6 +861,7 @@ TEST(VariationsSeedStoreTest, StoreSafeSeed_PreviouslyIdenticalToLatestSeed) {
TestVariationsSeedStore seed_store(&prefs);
base::HistogramTester histogram_tester;
EXPECT_TRUE(seed_store.StoreSafeSeed(serialized_new_seed, signature,
+ unused_seed_milestone,
unused_client_state, fetch_time));
// Verify the latest seed value was copied before the safe seed was
@@ -932,7 +890,7 @@ TEST(VariationsSeedStoreTest, StoreSafeSeed_PreviouslyIdenticalToLatestSeed) {
// Verify metrics.
histogram_tester.ExpectUniqueSample(
- "Variations.SafeMode.StoreSafeSeed.Result", StoreSeedResult::SUCCESS, 1);
+ "Variations.SafeMode.StoreSafeSeed.Result", StoreSeedResult::kSuccess, 1);
}
TEST(VariationsSeedStoreTest, StoreSeedData_GzippedEmptySeed) {
diff --git a/chromium/components/variations/variations_test_utils_unittest.cc b/chromium/components/variations/variations_test_utils_unittest.cc
index b717044ec78..6e0260270fb 100644
--- a/chromium/components/variations/variations_test_utils_unittest.cc
+++ b/chromium/components/variations/variations_test_utils_unittest.cc
@@ -67,8 +67,8 @@ TEST_P(SignedSeedDataTest, HasStudyNames) {
signed_seed_data.study_names));
}
-INSTANTIATE_TEST_CASE_P(VariationsTestUtils,
- SignedSeedDataTest,
- ::testing::Values(kTestSeedData, kCrashingSeedData));
+INSTANTIATE_TEST_SUITE_P(VariationsTestUtils,
+ SignedSeedDataTest,
+ ::testing::Values(kTestSeedData, kCrashingSeedData));
-} // namespace variations \ No newline at end of file
+} // namespace variations