blob: 988ba87cefa397dd3098cce603d7b19bee3891d4 [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 "content/browser/attribution_reporting/attribution_resolver_delegate_impl.h"
#include <stddef.h>
#include <stdint.h>
#include <cstdlib>
#include <iterator>
#include <optional>
#include <utility>
#include <vector>
#include "base/feature_list.h"
#include "base/memory/ptr_util.h"
#include "base/rand_util.h"
#include "base/time/time.h"
#include "base/types/expected_macros.h"
#include "base/uuid.h"
#include "components/attribution_reporting/aggregatable_trigger_config.h"
#include "components/attribution_reporting/attribution_scopes_data.h"
#include "components/attribution_reporting/event_level_epsilon.h"
#include "components/attribution_reporting/event_report_windows.h"
#include "components/attribution_reporting/features.h"
#include "components/attribution_reporting/max_event_level_reports.h"
#include "components/attribution_reporting/privacy_math.h"
#include "components/attribution_reporting/source_registration_time_config.mojom.h"
#include "components/attribution_reporting/source_type.mojom.h"
#include "components/attribution_reporting/trigger_config.h"
#include "content/browser/attribution_reporting/attribution_config.h"
#include "content/browser/attribution_reporting/attribution_report.h"
#include "content/browser/attribution_reporting/stored_source.h"
namespace content {
namespace {
using ::attribution_reporting::mojom::SourceType;
} // namespace
// static
std::unique_ptr<AttributionResolverDelegate>
AttributionResolverDelegateImpl::CreateForTesting(
AttributionNoiseMode noise_mode,
AttributionDelayMode delay_mode,
const AttributionConfig& config) {
return base::WrapUnique(
new AttributionResolverDelegateImpl(noise_mode, delay_mode, config));
}
AttributionResolverDelegateImpl::AttributionResolverDelegateImpl(
AttributionNoiseMode noise_mode,
AttributionDelayMode delay_mode)
: AttributionResolverDelegateImpl(noise_mode,
delay_mode,
AttributionConfig()) {}
AttributionResolverDelegateImpl::AttributionResolverDelegateImpl(
AttributionNoiseMode noise_mode,
AttributionDelayMode delay_mode,
const AttributionConfig& config)
: AttributionResolverDelegate(config),
noise_mode_(noise_mode),
delay_mode_(delay_mode) {
DETACH_FROM_SEQUENCE(sequence_checker_);
}
AttributionResolverDelegateImpl::~AttributionResolverDelegateImpl() = default;
base::TimeDelta
AttributionResolverDelegateImpl::GetDeleteExpiredSourcesFrequency() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return base::Minutes(5);
}
base::TimeDelta
AttributionResolverDelegateImpl::GetDeleteExpiredRateLimitsFrequency() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return base::Minutes(5);
}
base::TimeDelta
AttributionResolverDelegateImpl::GetDeleteExpiredOsRegistrationsFrequency()
const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return base::Minutes(5);
}
base::Time AttributionResolverDelegateImpl::GetEventLevelReportTime(
const attribution_reporting::EventReportWindows& event_report_windows,
base::Time source_time,
base::Time trigger_time) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
switch (delay_mode_) {
case AttributionDelayMode::kDefault:
return event_report_windows.ComputeReportTime(source_time, trigger_time);
case AttributionDelayMode::kNone:
return trigger_time;
}
}
base::Time AttributionResolverDelegateImpl::GetAggregatableReportTime(
base::Time trigger_time) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
switch (delay_mode_) {
case AttributionDelayMode::kDefault:
switch (noise_mode_) {
case AttributionNoiseMode::kDefault:
return trigger_time + config_.aggregate_limit.min_delay +
base::RandDouble() * config_.aggregate_limit.delay_span;
case AttributionNoiseMode::kNone:
return trigger_time + config_.aggregate_limit.min_delay +
config_.aggregate_limit.delay_span;
}
case AttributionDelayMode::kNone:
return trigger_time;
}
}
base::Uuid AttributionResolverDelegateImpl::NewReportID() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return base::Uuid::GenerateRandomV4();
}
std::optional<AttributionResolverDelegate::OfflineReportDelayConfig>
AttributionResolverDelegateImpl::GetOfflineReportDelayConfig() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (noise_mode_ == AttributionNoiseMode::kDefault &&
delay_mode_ == AttributionDelayMode::kDefault) {
// Add uniform random noise in the range of [0, 1 minutes] to the report
// time.
// TODO(crbug.com/40687765): This delay is very conservative.
// Consider increasing this delay once we can be sure reports are still
// sent at reasonable times, and not delayed for many browser sessions due
// to short session up-times.
return OfflineReportDelayConfig{
.min = base::Minutes(0),
.max = base::Minutes(1),
};
}
return std::nullopt;
}
void AttributionResolverDelegateImpl::ShuffleReports(
std::vector<AttributionReport>& reports) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
switch (noise_mode_) {
case AttributionNoiseMode::kDefault:
base::RandomShuffle(reports.begin(), reports.end());
break;
case AttributionNoiseMode::kNone:
break;
}
}
AttributionResolverDelegate::GetRandomizedResponseResult
AttributionResolverDelegateImpl::GetRandomizedResponse(
SourceType source_type,
const attribution_reporting::TriggerDataSet& trigger_data,
const attribution_reporting::EventReportWindows& event_report_windows,
const attribution_reporting::MaxEventLevelReports max_event_level_reports,
attribution_reporting::EventLevelEpsilon epsilon,
const std::optional<attribution_reporting::AttributionScopesData>&
scopes_data) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
ASSIGN_OR_RETURN(
auto response,
attribution_reporting::DoRandomizedResponse(
trigger_data, event_report_windows, max_event_level_reports, epsilon,
source_type, scopes_data, config_.privacy_math_config));
switch (noise_mode_) {
case AttributionNoiseMode::kDefault:
break;
case AttributionNoiseMode::kNone:
// TODO(apaseltiner): When noise is disabled, we shouldn't even bother
// generating the response in the first place.
response.response() = std::nullopt;
break;
}
return response;
}
bool AttributionResolverDelegateImpl::
GenerateNullAggregatableReportForLookbackDay(
int lookback_day,
attribution_reporting::mojom::SourceRegistrationTimeConfig
source_registration_time_config) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
switch (noise_mode_) {
case AttributionNoiseMode::kDefault:
break;
case AttributionNoiseMode::kNone:
return false;
}
double rate;
switch (source_registration_time_config) {
case attribution_reporting::mojom::SourceRegistrationTimeConfig::kInclude:
rate = config_.aggregate_limit
.null_reports_rate_include_source_registration_time;
break;
case attribution_reporting::mojom::SourceRegistrationTimeConfig::kExclude:
rate = config_.aggregate_limit
.null_reports_rate_exclude_source_registration_time;
break;
}
return attribution_reporting::GenerateWithRate(rate);
}
} // namespace content