blob: f3f25789f918cf2e182228df91f64a2a66df93d1 [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_VARIATIONS_SEED_READER_WRITER_H_
#define COMPONENTS_VARIATIONS_SEED_READER_WRITER_H_
#include <string>
#include "base/component_export.h"
#include "base/files/file_path.h"
#include "base/files/important_file_writer.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/version_info/channel.h"
class PrefService;
namespace variations {
class EntropyProviders;
// Trial and group names for the seed file experiment.
const char kSeedFileTrial[] = "SeedFileTrial";
const char kDefaultGroup[] = "Default";
const char kControlGroup[] = "Control_V7";
const char kSeedFilesGroup[] = "SeedFiles_V7";
// Represents a seed and its storage format where clients using
// seed-file-based seeds store compressed data and those using
// local-state-based seeds store compressed, base64 encoded data.
struct StoredSeed {
enum class StorageFormat { kCompressed, kCompressedAndBase64Encoded };
StorageFormat storage_format;
std::string_view data;
};
// TODO(crbug.com/380465790): Represents the seed and other related info.
// This info will be stored together in the SeedFile. Once all the seed-related
// info is stored in the struct, change it to a proto and use it to serialize
// and deserialize the data.
struct SeedInfo {
std::string data;
};
// Handles reading and writing seeds to disk.
class COMPONENT_EXPORT(VARIATIONS) SeedReaderWriter
: public base::ImportantFileWriter::BackgroundDataSerializer {
public:
// `local_state` provides access to the local state prefs. Must not be null.
// `seed_file_dir` denotes the directory for storing a seed file. Note that
// Android Webview intentionally uses an empty path as it uses only local
// state to store seeds.
// `seed_filename` is the base name of a file in which seed data is stored.
// `seed_pref` is a variations pref (kVariationsCompressedSeed or
// kVariationsSafeCompressed) denoting the type of seed handled by this
// SeedReaderWriter.
// `channel` describes the release channel of the browser.
// `entropy_providers` is used to provide entropy when setting up the seed
// file field trial. If null, the client will not participate in the
// experiment.
// `file_task_runner` handles IO-related tasks. Must not be null.
SeedReaderWriter(PrefService* local_state,
const base::FilePath& seed_file_dir,
base::FilePath::StringViewType seed_filename,
std::string_view seed_pref,
version_info::Channel channel,
const EntropyProviders* entropy_providers,
scoped_refptr<base::SequencedTaskRunner> file_task_runner =
base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN}));
SeedReaderWriter(const SeedReaderWriter&) = delete;
SeedReaderWriter& operator=(const SeedReaderWriter&) = delete;
~SeedReaderWriter() override;
// Schedules a write of `base64_seed_data` to local state. For some clients
// (see ShouldUseSeedFile()), also schedules a write of `compressed_seed_data`
// to a seed file.
void StoreValidatedSeed(std::string_view compressed_seed_data,
std::string_view base64_seed_data);
// Clears seed data by overwriting it with an empty string.
void ClearSeed();
// Returns stored seed data.
StoredSeed GetSeedData() const;
// Overrides the timer used for scheduling writes with `timer_override`.
void SetTimerForTesting(base::OneShotTimer* timer_override);
private:
// Returns the serialized data to be written to disk. This is done
// asynchronously during the write process.
base::ImportantFileWriter::BackgroundDataProducerCallback
GetSerializedDataProducerForBackgroundSequence() override;
// Schedules `seed_data` to be written using `seed_writer_`.
void ScheduleSeedFileWrite(std::string_view seed_data);
// Schedules the deletion of a seed file.
void DeleteSeedFile();
// Reads seed data from a seed file, and if the read is successful,
// populates `seed_info_`. May also schedule a seed file write for some
// clients on the first run and for clients that are in the seed file
// experiment's treatment group for the first time. If `seed_pref_` is present
// in `local state_`, additionally clears it.
void ReadSeedFile();
// Returns true if a seed file should be used.
bool ShouldUseSeedFile() const;
// Pref service used to persist seeds.
raw_ptr<PrefService> local_state_;
// A variations pref (kVariationsCompressedSeed or kVariationsSafeCompressed)
// denoting the type of seed handled by this SeedReaderWriter.
std::string_view seed_pref_;
// Task runner for IO-related operations.
const scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
// Helper for safely writing a seed. Null if a seed file path is not given.
std::unique_ptr<base::ImportantFileWriter> seed_writer_;
// Stored seed info. Used to store a seed applied during field trial
// setup or a seed fetched from a variations server. Also stores other
// seed-related info.
SeedInfo seed_info_;
SEQUENCE_CHECKER(sequence_checker_);
};
} // namespace variations
#endif // COMPONENTS_VARIATIONS_SEED_READER_WRITER_H_