blob: 91004f63abc9de6e3a79ee63d9642fad43b239e1 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/feed/core/v2/config.h"
#include "base/command_line.h"
#include "base/containers/flat_set.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/strcat.h"
#include "components/feed/core/proto/v2/wire/capability.pb.h"
#include "components/feed/core/v2/public/stream_type.h"
#include "components/feed/feed_feature_list.h"
namespace feed {
namespace {
// A note about the design.
// Soon, we'll add the ability to override configuration values from sources
// other than Finch. Finch serves well for experimentation, but after we're done
// experimenting, we still want to control some of these values. The tentative
// plan is to send configuration down from the server, and store it in prefs.
// The source of a config value would be the following, in order of preference:
// finch, server, default-value.
bool CapabilityDisabled(feedwire::Capability capability) {
return !base::GetFieldTrialParamByFeatureAsBool(
kInterestFeedV2,
base::StrCat({"enable_", feedwire::Capability_Name(capability)}), true);
}
// Override any parameters that may be provided by Finch.
void OverrideWithFinch(Config& config) {
config.max_feed_query_requests_per_day =
base::GetFieldTrialParamByFeatureAsInt(
kInterestFeedV2, "max_feed_query_requests_per_day",
config.max_feed_query_requests_per_day);
config.max_next_page_requests_per_day =
base::GetFieldTrialParamByFeatureAsInt(
kInterestFeedV2, "max_next_page_requests_per_day",
config.max_next_page_requests_per_day);
config.max_action_upload_requests_per_day =
base::GetFieldTrialParamByFeatureAsInt(
kInterestFeedV2, "max_action_upload_requests_per_day",
config.max_action_upload_requests_per_day);
config.stale_content_threshold =
base::Seconds(base::GetFieldTrialParamByFeatureAsDouble(
kInterestFeedV2, "stale_content_threshold_seconds",
config.stale_content_threshold.InSecondsF()));
config.content_expiration_threshold =
base::Seconds(base::GetFieldTrialParamByFeatureAsDouble(
kInterestFeedV2, "content_expiration_threshold_seconds",
config.content_expiration_threshold.InSecondsF()));
if (base::FeatureList::IsEnabled(kWebFeedOnboarding)) {
config.subscriptionless_content_expiration_threshold =
base::Seconds(base::GetFieldTrialParamByFeatureAsDouble(
kWebFeedOnboarding,
"subscriptionless_content_expiration_threshold_seconds",
config.subscriptionless_content_expiration_threshold.InSecondsF()));
}
config.background_refresh_window_length =
base::Seconds(base::GetFieldTrialParamByFeatureAsDouble(
kInterestFeedV2, "background_refresh_window_length_seconds",
config.background_refresh_window_length.InSecondsF()));
config.default_background_refresh_interval =
base::Seconds(base::GetFieldTrialParamByFeatureAsDouble(
kInterestFeedV2, "default_background_refresh_interval_seconds",
config.default_background_refresh_interval.InSecondsF()));
config.max_action_upload_attempts = base::GetFieldTrialParamByFeatureAsInt(
kInterestFeedV2, "max_action_upload_attempts",
config.max_action_upload_attempts);
config.max_action_age =
base::Seconds(base::GetFieldTrialParamByFeatureAsDouble(
kInterestFeedV2, "max_action_age_seconds",
config.max_action_age.InSecondsF()));
config.max_action_upload_bytes = base::GetFieldTrialParamByFeatureAsInt(
kInterestFeedV2, "max_action_upload_bytes",
config.max_action_upload_bytes);
config.model_unload_timeout =
base::Seconds(base::GetFieldTrialParamByFeatureAsDouble(
kInterestFeedV2, "model_unload_timeout_seconds",
config.model_unload_timeout.InSecondsF()));
config.load_more_trigger_lookahead = base::GetFieldTrialParamByFeatureAsInt(
kInterestFeedV2, "load_more_trigger_lookahead",
config.load_more_trigger_lookahead);
config.upload_actions_on_enter_background =
base::GetFieldTrialParamByFeatureAsBool(
kInterestFeedV2, "upload_actions_on_enter_background",
config.upload_actions_on_enter_background);
config.send_signed_out_session_logs = base::GetFieldTrialParamByFeatureAsBool(
kInterestFeedV2, "send_signed_out_session_logs",
config.send_signed_out_session_logs);
config.session_id_max_age = base::Days(base::GetFieldTrialParamByFeatureAsInt(
kInterestFeedV2, "session_id_max_age_days",
config.session_id_max_age.InDays()));
config.max_prefetch_image_requests_per_refresh =
base::GetFieldTrialParamByFeatureAsInt(
kInterestFeedV2, "max_prefetch_image_requests_per_refresh",
config.max_prefetch_image_requests_per_refresh);
if (base::FeatureList::IsEnabled(kWebFeedOnboarding)) {
config.subscriptionless_web_feed_stale_content_threshold =
base::Seconds(base::GetFieldTrialParamByFeatureAsDouble(
kWebFeedOnboarding,
"subscriptionless_web_feed_stale_content_threshold_seconds",
config.subscriptionless_web_feed_stale_content_threshold
.InSecondsF()));
}
// Erase any capabilities with "enable_CAPABILITY = false" set.
base::EraseIf(config.experimental_capabilities, CapabilityDisabled);
config.max_mid_entities_per_url_entry =
base::GetFieldTrialParamByFeatureAsInt(
kPersonalizeFeedUnsignedUsers, "max_mid_entities_per_url_entry",
config.max_mid_entities_per_url_entry);
config.max_url_entries_in_cache = GetFieldTrialParamByFeatureAsInt(
kPersonalizeFeedUnsignedUsers, "max_url_entries_in_cache",
config.max_url_entries_in_cache);
}
void OverrideWithSwitches(Config& config) {
config.use_feed_query_requests =
base::CommandLine::ForCurrentProcess()->HasSwitch("use-legacy-feedquery");
}
} // namespace
const Config& GetFeedConfig() {
static Config* s_config = nullptr;
if (!s_config) {
s_config = new Config;
OverrideWithFinch(*s_config);
OverrideWithSwitches(*s_config);
}
return *s_config;
}
// This is a dev setting that updates Config, which is supposed to be constant.
void SetUseFeedQueryRequests(const bool use_legacy) {
Config& config = const_cast<Config&>(GetFeedConfig());
config.use_feed_query_requests = use_legacy;
}
void SetFeedConfigForTesting(const Config& config) {
const_cast<Config&>(GetFeedConfig()) = config;
}
void OverrideConfigWithFinchForTesting() {
OverrideWithFinch(const_cast<Config&>(GetFeedConfig()));
}
Config::Config() = default;
Config::Config(const Config& other) = default;
Config::~Config() = default;
base::TimeDelta Config::GetStalenessThreshold(const StreamType& stream_type,
bool has_subscriptions) const {
if (stream_type.IsForYou()) {
return stale_content_threshold;
}
if (has_subscriptions) {
return web_feed_stale_content_threshold;
}
return subscriptionless_web_feed_stale_content_threshold;
}
} // namespace feed