| Index: components/ntp_snippets/request_throttler.cc
|
| diff --git a/components/ntp_snippets/request_throttler.cc b/components/ntp_snippets/request_throttler.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3055375aacbdc379101f1c12b6ec785c9e5a922d
|
| --- /dev/null
|
| +++ b/components/ntp_snippets/request_throttler.cc
|
| @@ -0,0 +1,149 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "components/ntp_snippets/request_throttler.h"
|
| +
|
| +#include <vector>
|
| +
|
| +#include "base/metrics/histogram.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| +#include "base/strings/string_split.h"
|
| +#include "base/strings/stringprintf.h"
|
| +#include "base/time/time.h"
|
| +#include "components/ntp_snippets/ntp_snippets_constants.h"
|
| +#include "components/ntp_snippets/pref_names.h"
|
| +#include "components/prefs/pref_registry_simple.h"
|
| +#include "components/prefs/pref_service.h"
|
| +#include "components/variations/variations_associated_data.h"
|
| +
|
| +namespace ntp_snippets {
|
| +
|
| +// Used internally for working with a RequestType.
|
| +struct RequestTypeInfo {
|
| + const char* name;
|
| + const char* count_pref;
|
| + const char* day_pref;
|
| +};
|
| +
|
| +namespace {
|
| +
|
| +// Enumeration listing all possible outcomes for fetch attempts. Used for UMA
|
| +// histogram, so do not change existing values. Insert new values at the end,
|
| +// and update the histogram definition.
|
| +enum class RequestStatus {
|
| + FORCED,
|
| + QUOTA_GRANTED,
|
| + QUOTA_EXCEEDED,
|
| + REQUEST_STATUS_COUNT
|
| +};
|
| +
|
| +// When adding a new type here, extend also the "RequestCounterTypes"
|
| +// <histogram_suffixes> in histograms.xml with the |name| string.
|
| +const RequestTypeInfo kRequestTypeInfo[] = {
|
| + // RequestCounter::RequestType::CONTENT_SUGGESTION_FETCHER,
|
| + {"SuggestionFetcher", prefs::kSnippetFetcherQuotaCount,
|
| + prefs::kSnippetFetcherQuotaDay}};
|
| +
|
| +} // namespace
|
| +
|
| +RequestThrottler::RequestThrottler(PrefService* pref_service,
|
| + RequestType type,
|
| + int default_quota)
|
| + : pref_service_(pref_service),
|
| + type_info_(kRequestTypeInfo[static_cast<int>(type)]) {
|
| + DCHECK(pref_service);
|
| +
|
| + std::string quota = variations::GetVariationParamValue(
|
| + ntp_snippets::kStudyName,
|
| + base::StringPrintf("quota_%s", GetRequestTypeAsString()));
|
| + if (!base::StringToInt(quota, "a_)) {
|
| + LOG_IF(WARNING, !quota.empty())
|
| + << "Invalid variation parameter for quota for "
|
| + << GetRequestTypeAsString();
|
| + quota_ = default_quota;
|
| + }
|
| +
|
| + // Since the histogram names are dynamic, we cannot use the standard macros
|
| + // and we need to lookup the histograms, instead.
|
| + int status_count = static_cast<int>(RequestStatus::REQUEST_STATUS_COUNT);
|
| + // Corresponds to UMA_HISTOGRAM_ENUMERATION(name, sample, |status_count|).
|
| + histogram_request_status_ = base::LinearHistogram::FactoryGet(
|
| + base::StringPrintf("NewTabPage.RequestThrottler.RequestStatus_%s",
|
| + GetRequestTypeAsString()),
|
| + 1, status_count, status_count + 1,
|
| + base::HistogramBase::kUmaTargetedHistogramFlag);
|
| + // Corresponds to UMA_HISTOGRAM_COUNTS_100(name, sample).
|
| + histogram_per_day_ = base::Histogram::FactoryGet(
|
| + base::StringPrintf("NewTabPage.RequestThrottler.PerDay_%s",
|
| + GetRequestTypeAsString()),
|
| + 1, 100, 50, base::HistogramBase::kUmaTargetedHistogramFlag);
|
| +}
|
| +
|
| +// static
|
| +void RequestThrottler::RegisterProfilePrefs(PrefRegistrySimple* registry) {
|
| + for (const RequestTypeInfo& info : kRequestTypeInfo) {
|
| + registry->RegisterIntegerPref(info.count_pref, 0);
|
| + registry->RegisterIntegerPref(info.day_pref, 0);
|
| + }
|
| +}
|
| +
|
| +bool RequestThrottler::DemandQuotaForRequest(bool forced_request) {
|
| + ResetCounterIfDayChanged();
|
| +
|
| + if (forced_request) {
|
| + histogram_request_status_->Add(static_cast<int>(RequestStatus::FORCED));
|
| + return true;
|
| + }
|
| +
|
| + int new_count = GetCount() + 1;
|
| + SetCount(new_count);
|
| + bool available = (new_count <= quota_);
|
| +
|
| + histogram_request_status_->Add(
|
| + static_cast<int>(available ? RequestStatus::QUOTA_GRANTED
|
| + : RequestStatus::QUOTA_EXCEEDED));
|
| + return available;
|
| +}
|
| +
|
| +void RequestThrottler::ResetCounterIfDayChanged() {
|
| + // The count of days since a fixed reference (the Unix epoch).
|
| + int now_day = (base::Time::Now() - base::Time::UnixEpoch()).InDays();
|
| +
|
| + if (!HasDay()) {
|
| + // The counter is used for the first time in this profile.
|
| + SetDay(now_day);
|
| + } else if (now_day != GetDay()) {
|
| + // Day has changed - report the number of requests from the previous day.
|
| + histogram_per_day_->Add(GetCount());
|
| + // Reset the counter.
|
| + SetCount(0);
|
| + SetDay(now_day);
|
| + }
|
| +}
|
| +
|
| +const char* RequestThrottler::GetRequestTypeAsString() const {
|
| + return type_info_.name;
|
| +}
|
| +
|
| +int RequestThrottler::GetCount() const {
|
| + return pref_service_->GetInteger(type_info_.count_pref);
|
| +}
|
| +
|
| +void RequestThrottler::SetCount(int count) {
|
| + pref_service_->SetInteger(type_info_.count_pref, count);
|
| +}
|
| +
|
| +int RequestThrottler::GetDay() const {
|
| + return pref_service_->GetInteger(type_info_.day_pref);
|
| +}
|
| +
|
| +void RequestThrottler::SetDay(int day) {
|
| + pref_service_->SetInteger(type_info_.day_pref, day);
|
| +}
|
| +
|
| +bool RequestThrottler::HasDay() const {
|
| + return pref_service_->HasPrefPath(type_info_.day_pref);
|
| +}
|
| +
|
| +} // namespace ntp_snippets
|
|
|