0

Add command line flag to override campaigns.

The value is based64 encoded string. Also expose it as chrome flag.

Bug: b/333140151
Change-Id: I6025d346bf57bd4dd17440a5e6fcfe47eff8d666
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5431446
Reviewed-by: Tao Wu <wutao@chromium.org>
Commit-Queue: Li Lin <llin@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1284128}
This commit is contained in:
Li Lin
2024-04-08 22:16:20 +00:00
committed by Chromium LUCI CQ
parent 8bd641ae41
commit 1ac8492a0d
7 changed files with 70 additions and 10 deletions

@ -712,6 +712,9 @@ const char kGlanceablesKeyExpectedHash[] =
"\xe2\xcb";
const char kGlanceablesKeySwitch[] = "glanceables-key";
// Specifies campaigns to override for testing.
const char kGrowthCampaigns[] = "growth-campaigns";
// Path for which to load growth campaigns file for testing (instead of
// downloading from Omaha).
const char kGrowthCampaignsPath[] = "growth-campaigns-path";

@ -228,6 +228,7 @@ COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kForestFeatureKey[];
COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kFormFactor[];
COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kGlanceablesKeyExpectedHash[];
COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kGlanceablesKeySwitch[];
COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kGrowthCampaigns[];
COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kGrowthCampaignsPath[];
COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kGuestSession[];
COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kGuestWallpaperLarge[];

@ -3156,6 +3156,8 @@ constexpr char kClipboardHistoryUrlTitlesInternalName[] =
constexpr char kBluetoothUseFlossInternalName[] = "bluetooth-use-floss";
constexpr char kSeaPenInternalName[] = "sea-pen";
constexpr char kAssistantIphInternalName[] = "assistant-iph";
constexpr char kGrowthCampaigns[] = "growth-campaigns";
constexpr char kGrowthCampaignsTestTag[] = "campaigns-test-tag";
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
#if !BUILDFLAG(IS_ANDROID) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
@ -9339,11 +9341,15 @@ const FeatureEntry kFeatureEntries[] = {
SINGLE_VALUE_TYPE_AND_VALUE(switches::kComponentUpdater,
component_updater::kSwitchTestRequestParam)},
{"campaigns-test-tag",
{kGrowthCampaignsTestTag,
flag_descriptions::kCampaignsComponentUpdaterTestTagName,
flag_descriptions::kCampaignsComponentUpdaterTestTagDescription, kOsCrOS,
STRING_VALUE_TYPE(switches::kCampaignsTestTag, "")},
{kGrowthCampaigns, flag_descriptions::kCampaignsOverrideName,
flag_descriptions::kCampaignsOverrideDescription, kOsCrOS,
STRING_VALUE_TYPE(ash::switches::kGrowthCampaigns, "")},
{"demo-mode-test-tag",
flag_descriptions::kDemoModeComponentUpdaterTestTagName,
flag_descriptions::kDemoModeComponentUpdaterTestTagDescription, kOsCrOS,
@ -11453,6 +11459,24 @@ bool ShouldSkipConditionalFeatureEntry(const flags_ui::FlagsStorage* storage,
channel != version_info::Channel::CANARY &&
channel != version_info::Channel::UNKNOWN;
}
// Only show Growth campaigns flag if channel is one of Beta/Dev/Canary/
// Unknown.
if (!strcmp(kGrowthCampaigns, entry.internal_name)) {
return channel != version_info::Channel::BETA &&
channel != version_info::Channel::DEV &&
channel != version_info::Channel::CANARY &&
channel != version_info::Channel::UNKNOWN;
}
// Only show Growth campaigns test tag flag if channel is one of
// Beta/Dev/Canary/ Unknown.
if (!strcmp(kGrowthCampaignsTestTag, entry.internal_name)) {
return channel != version_info::Channel::BETA &&
channel != version_info::Channel::DEV &&
channel != version_info::Channel::CANARY &&
channel != version_info::Channel::UNKNOWN;
}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
if (flags::IsFlagExpired(storage, entry.internal_name)) {
return true;

@ -4707,6 +4707,11 @@
"owners": [ "ckitagawa@google.com", "clank-isochron-team@google.com" ],
"expiry_milestone": 125
},
{
"name": "growth-campaigns",
"owners": [ "llin@google.com", "cros-growth@google.com" ],
"expiry_milestone": 130
},
{
"name": "handwriting-legacy-recognition",
"owners": [ "curtismcmullan@chromium.org", "essential-inputs-team@google.com" ],

@ -5918,6 +5918,9 @@ const char kCampaignsComponentUpdaterTestTagName[] = "Campaigns test tag";
const char kCampaignsComponentUpdaterTestTagDescription[] =
"Tags used for component updater to selet Omaha cohort for Growth "
"Campaigns.";
const char kCampaignsOverrideName[] = "Campaigns override";
const char kCampaignsOverrideDescription[] =
"Base64 encoded Growth campaigns used for testing.";
#endif // IS_CHROMEOS_ASH
const char kComponentUpdaterTestRequestName[] =

@ -103,6 +103,8 @@ extern const char kBackgroundResourceFetchDescription[];
#if BUILDFLAG(IS_CHROMEOS_ASH)
extern const char kCampaignsComponentUpdaterTestTagName[];
extern const char kCampaignsComponentUpdaterTestTagDescription[];
extern const char kCampaignsOverrideName[];
extern const char kCampaignsOverrideDescription[];
#endif // IS_CHROMEOS_ASH
extern const char kCOLRV1FontsDescription[];

@ -6,6 +6,9 @@
#include <optional>
#include "ash/constants/ash_switches.h"
#include "base/base64.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
@ -32,6 +35,18 @@ inline constexpr char kEventKey[] = "event_to_be_cleared";
inline constexpr char kEventTemplate[] =
"name:%s;comparator:any;window:365;storage:365";
std::optional<base::Value::Dict> ParseCampaignsFile(
const std::string& campaigns_data) {
std::optional<base::Value> value(base::JSONReader::Read(campaigns_data));
if (!value || !value->is_dict()) {
LOG(ERROR) << "Failed to parse campaigns file: " << campaigns_data;
RecordCampaignsManagerError(CampaignsManagerError::kCampaignsParsingFail);
return std::nullopt;
}
return std::move(value->GetDict());
}
std::optional<base::Value::Dict> ReadCampaignsFile(
const base::FilePath& campaigns_component_path) {
const auto campaigns_load_start_time = base::TimeTicks::Now();
@ -47,18 +62,11 @@ std::optional<base::Value::Dict> ReadCampaignsFile(
return std::nullopt;
}
std::optional<base::Value> value(base::JSONReader::Read(campaigns_data));
if (!value || !value->is_dict()) {
LOG(ERROR) << "Failed to parse campaigns file.";
RecordCampaignsManagerError(CampaignsManagerError::kCampaignsParsingFail);
RecordCampaignsComponentReadDuration(base::TimeTicks::Now() -
campaigns_load_start_time);
return std::nullopt;
}
auto parse_result = ParseCampaignsFile(campaigns_data);
RecordCampaignsComponentReadDuration(base::TimeTicks::Now() -
campaigns_load_start_time);
return std::move(value->GetDict());
return parse_result;
}
void LogCampaignInSystemLog(const Campaign* campaign, Slot slot) {
@ -132,6 +140,20 @@ void CampaignsManager::SetPrefs(PrefService* prefs) {
void CampaignsManager::LoadCampaigns(base::OnceClosure load_callback,
bool in_oobe) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(ash::switches::kGrowthCampaigns)) {
const auto& value =
command_line->GetSwitchValueASCII(ash::switches::kGrowthCampaigns);
std::string decoded_str;
if (base::Base64Decode(value, &decoded_str)) {
OnCampaignsLoaded(std::move(load_callback),
ParseCampaignsFile(decoded_str));
return;
} else {
LOG(ERROR) << "Failed decode base64 encoded campaigns string.";
}
}
campaigns_download_start_time_ = base::TimeTicks::Now();
client_->LoadCampaignsComponent(base::BindOnce(
&CampaignsManager::OnCampaignsComponentLoaded, weak_factory_.GetWeakPtr(),