blob: b00f0a67c5e58af52ce0525177979073017d96d9 [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_test_utils.h"
#include <limits.h>
#include <stdint.h>
#include <algorithm>
#include <limits>
#include <tuple>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/check.h"
#include "base/check_op.h"
#include "base/ranges/algorithm.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/bind.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "components/attribution_reporting/aggregatable_trigger_data.h"
#include "components/attribution_reporting/event_trigger_data.h"
#include "components/attribution_reporting/filters.h"
#include "components/attribution_reporting/source_registration.h"
#include "components/attribution_reporting/source_registration_error.mojom.h"
#include "components/attribution_reporting/suitable_origin.h"
#include "components/attribution_reporting/trigger_registration.h"
#include "content/browser/attribution_reporting/attribution_observer.h"
#include "content/browser/attribution_reporting/attribution_source_type.h"
#include "content/browser/attribution_reporting/rate_limit_result.h"
#include "content/public/browser/attribution_config.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "net/base/net_errors.h"
#include "third_party/abseil-cpp/absl/numeric/int128.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#if BUILDFLAG(IS_ANDROID)
#include "content/browser/attribution_reporting/attribution_input_event_tracker_android.h"
#endif
namespace content {
namespace {
using ::attribution_reporting::SuitableOrigin;
using ::testing::AllOf;
using ::testing::Field;
using ::testing::Property;
const char kDefaultSourceOrigin[] = "https://impression.test/";
const char kDefaultDestinationOrigin[] = "https://sub.conversion.test/";
const char kDefaultReportOrigin[] = "https://report.test/";
// Default expiry time for impressions for testing.
const int64_t kExpiryTime = 30;
} // namespace
MockAttributionReportingContentBrowserClient::
MockAttributionReportingContentBrowserClient() = default;
MockAttributionReportingContentBrowserClient::
~MockAttributionReportingContentBrowserClient() = default;
// static
MockAttributionHost* MockAttributionHost::Override(WebContents* web_contents) {
#if BUILDFLAG(IS_ANDROID)
auto* old_host = AttributionHost::FromWebContents(web_contents);
if (auto* input_event_tracker = old_host->input_event_tracker()) {
input_event_tracker->RemoveObserverForTesting(web_contents);
}
#endif
auto host = base::WrapUnique(new MockAttributionHost(web_contents));
auto* raw = host.get();
web_contents->SetUserData(AttributionHost::UserDataKey(), std::move(host));
return raw;
}
MockAttributionHost::MockAttributionHost(WebContents* web_contents)
: AttributionHost(web_contents) {}
MockAttributionHost::~MockAttributionHost() = default;
MockDataHost::MockDataHost(
mojo::PendingReceiver<blink::mojom::AttributionDataHost> data_host) {
receiver_.Bind(std::move(data_host));
}
MockDataHost::~MockDataHost() = default;
void MockDataHost::WaitForSourceData(size_t num_source_data) {
min_source_data_count_ = num_source_data;
if (source_data_.size() >= min_source_data_count_) {
return;
}
wait_loop_.Run();
}
void MockDataHost::WaitForTriggerData(size_t num_trigger_data) {
min_trigger_data_count_ = num_trigger_data;
if (trigger_data_.size() >= min_trigger_data_count_) {
return;
}
wait_loop_.Run();
}
void MockDataHost::SourceDataAvailable(
attribution_reporting::SourceRegistration data) {
source_data_.push_back(std::move(data));
if (source_data_.size() < min_source_data_count_) {
return;
}
wait_loop_.Quit();
}
void MockDataHost::TriggerDataAvailable(
attribution_reporting::TriggerRegistration data) {
trigger_data_.push_back(std::move(data));
if (trigger_data_.size() < min_trigger_data_count_) {
return;
}
wait_loop_.Quit();
}
MockDataHostManager::MockDataHostManager() = default;
MockDataHostManager::~MockDataHostManager() = default;
MockAttributionObserver::MockAttributionObserver() = default;
MockAttributionObserver::~MockAttributionObserver() = default;
base::GUID DefaultExternalReportID() {
return base::GUID::ParseLowercase("21abd97f-73e8-4b88-9389-a9fee6abda5e");
}
std::vector<base::GUID> DefaultExternalReportIDs(size_t size) {
return std::vector<base::GUID>(size, DefaultExternalReportID());
}
ConfigurableStorageDelegate::ConfigurableStorageDelegate()
: AttributionStorageDelegate(AttributionConfig{
.max_sources_per_origin = std::numeric_limits<int>::max(),
.source_event_id_cardinality = absl::nullopt,
.max_destinations_per_source_site_reporting_origin =
std::numeric_limits<int>::max(),
.rate_limit =
{
.time_window = base::TimeDelta::Max(),
.max_source_registration_reporting_origins =
std::numeric_limits<int64_t>::max(),
.max_attribution_reporting_origins =
std::numeric_limits<int64_t>::max(),
.max_attributions = std::numeric_limits<int64_t>::max(),
},
.event_level_limit =
{
.navigation_source_trigger_data_cardinality =
std::numeric_limits<uint64_t>::max(),
.event_source_trigger_data_cardinality =
std::numeric_limits<uint64_t>::max(),
.navigation_source_randomized_response_rate = 0,
.event_source_randomized_response_rate = 0,
.max_reports_per_destination =
std::numeric_limits<int>::max(),
.max_attributions_per_navigation_source =
std::numeric_limits<int>::max(),
.max_attributions_per_event_source =
std::numeric_limits<int>::max(),
},
.aggregate_limit =
{
.max_reports_per_destination =
std::numeric_limits<int>::max(),
.aggregatable_budget_per_source =
std::numeric_limits<int64_t>::max(),
.min_delay = base::TimeDelta(),
.delay_span = base::TimeDelta(),
},
}) {}
ConfigurableStorageDelegate::~ConfigurableStorageDelegate() = default;
void ConfigurableStorageDelegate::DetachFromSequence() {
DETACH_FROM_SEQUENCE(sequence_checker_);
}
base::Time ConfigurableStorageDelegate::GetEventLevelReportTime(
const CommonSourceInfo& source,
base::Time trigger_time) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return source.source_time() + report_delay_;
}
base::Time ConfigurableStorageDelegate::GetAggregatableReportTime(
base::Time trigger_time) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return trigger_time + report_delay_;
}
base::TimeDelta ConfigurableStorageDelegate::GetDeleteExpiredSourcesFrequency()
const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return delete_expired_sources_frequency_;
}
base::TimeDelta
ConfigurableStorageDelegate::GetDeleteExpiredRateLimitsFrequency() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return delete_expired_rate_limits_frequency_;
}
base::GUID ConfigurableStorageDelegate::NewReportID() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return DefaultExternalReportID();
}
absl::optional<AttributionStorageDelegate::OfflineReportDelayConfig>
ConfigurableStorageDelegate::GetOfflineReportDelayConfig() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return offline_report_delay_config_;
}
void ConfigurableStorageDelegate::ShuffleReports(
std::vector<AttributionReport>& reports) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (reverse_reports_on_shuffle_)
base::ranges::reverse(reports);
}
AttributionStorageDelegate::RandomizedResponse
ConfigurableStorageDelegate::GetRandomizedResponse(
const CommonSourceInfo& source) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return randomized_response_;
}
void ConfigurableStorageDelegate::set_max_attributions_per_source(int max) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
config_.event_level_limit.max_attributions_per_navigation_source = max;
config_.event_level_limit.max_attributions_per_event_source = max;
}
void ConfigurableStorageDelegate::set_max_sources_per_origin(int max) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
config_.max_sources_per_origin = max;
}
void ConfigurableStorageDelegate::set_max_reports_per_destination(
AttributionReport::Type report_type,
int max) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
switch (report_type) {
case AttributionReport::Type::kEventLevel:
config_.event_level_limit.max_reports_per_destination = max;
break;
case AttributionReport::Type::kAggregatableAttribution:
config_.aggregate_limit.max_reports_per_destination = max;
break;
}
}
void ConfigurableStorageDelegate::
set_max_destinations_per_source_site_reporting_origin(int max) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
config_.max_destinations_per_source_site_reporting_origin = max;
}
void ConfigurableStorageDelegate::set_aggregatable_budget_per_source(
int64_t max) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
config_.aggregate_limit.aggregatable_budget_per_source = max;
}
void ConfigurableStorageDelegate::set_rate_limits(
AttributionConfig::RateLimitConfig c) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(c.Validate());
config_.rate_limit = c;
}
void ConfigurableStorageDelegate::set_delete_expired_sources_frequency(
base::TimeDelta frequency) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
delete_expired_sources_frequency_ = frequency;
}
void ConfigurableStorageDelegate::set_delete_expired_rate_limits_frequency(
base::TimeDelta frequency) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
delete_expired_rate_limits_frequency_ = frequency;
}
void ConfigurableStorageDelegate::set_report_delay(
base::TimeDelta report_delay) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
report_delay_ = report_delay;
}
void ConfigurableStorageDelegate::set_offline_report_delay_config(
absl::optional<OfflineReportDelayConfig> config) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
offline_report_delay_config_ = config;
}
void ConfigurableStorageDelegate::set_reverse_reports_on_shuffle(bool reverse) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
reverse_reports_on_shuffle_ = reverse;
}
void ConfigurableStorageDelegate::set_randomized_response_rates(
double navigation,
double event) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
config_.event_level_limit.navigation_source_randomized_response_rate =
navigation;
config_.event_level_limit.event_source_randomized_response_rate = event;
}
void ConfigurableStorageDelegate::set_randomized_response(
RandomizedResponse randomized_response) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
randomized_response_ = std::move(randomized_response);
}
void ConfigurableStorageDelegate::set_trigger_data_cardinality(
uint64_t navigation,
uint64_t event) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_GT(navigation, 0u);
DCHECK_GT(event, 0u);
config_.event_level_limit.navigation_source_trigger_data_cardinality =
navigation;
config_.event_level_limit.event_source_trigger_data_cardinality = event;
}
void ConfigurableStorageDelegate::set_source_event_id_cardinality(
uint64_t cardinality) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_GT(cardinality, 0u);
config_.source_event_id_cardinality = cardinality;
}
MockAttributionManager::MockAttributionManager() = default;
MockAttributionManager::~MockAttributionManager() = default;
void MockAttributionManager::AddObserver(AttributionObserver* observer) {
observers_.AddObserver(observer);
}
void MockAttributionManager::RemoveObserver(AttributionObserver* observer) {
observers_.RemoveObserver(observer);
}
AttributionDataHostManager* MockAttributionManager::GetDataHostManager() {
return data_host_manager_.get();
}
void MockAttributionManager::NotifySourcesChanged() {
for (auto& observer : observers_)
observer.OnSourcesChanged();
}
void MockAttributionManager::NotifyReportsChanged(
AttributionReport::Type report_type) {
for (auto& observer : observers_)
observer.OnReportsChanged(report_type);
}
void MockAttributionManager::NotifySourceHandled(
const StorableSource& source,
StorableSource::Result result,
absl::optional<uint64_t> cleared_debug_key) {
for (auto& observer : observers_)
observer.OnSourceHandled(source, cleared_debug_key, result);
}
void MockAttributionManager::NotifyReportSent(const AttributionReport& report,
bool is_debug_report,
const SendResult& info) {
for (auto& observer : observers_)
observer.OnReportSent(report, is_debug_report, info);
}
void MockAttributionManager::NotifySourceRegistrationFailure(
const std::string& header_value,
const SuitableOrigin& reporting_origin,
attribution_reporting::mojom::SourceRegistrationError error) {
base::Time source_time = base::Time::Now();
for (auto& observer : observers_) {
observer.OnFailedSourceRegistration(header_value, source_time,
reporting_origin, error);
}
}
void MockAttributionManager::NotifyTriggerHandled(
const AttributionTrigger& trigger,
const CreateReportResult& result,
absl::optional<uint64_t> cleared_debug_key) {
for (auto& observer : observers_)
observer.OnTriggerHandled(trigger, cleared_debug_key, result);
}
void MockAttributionManager::NotifyDebugReportSent(
const AttributionDebugReport& report,
const int status,
const base::Time time) {
for (auto& observer : observers_)
observer.OnDebugReportSent(report, status, time);
}
void MockAttributionManager::SetDataHostManager(
std::unique_ptr<AttributionDataHostManager> manager) {
data_host_manager_ = std::move(manager);
}
SourceObserver::SourceObserver(WebContents* contents, size_t num_impressions)
: TestNavigationObserver(contents),
expected_num_impressions_(num_impressions) {}
SourceObserver::~SourceObserver() = default;
void SourceObserver::OnDidFinishNavigation(
NavigationHandle* navigation_handle) {
if (!navigation_handle->GetImpression()) {
if (waiting_for_null_impression_)
impression_loop_.Quit();
return;
}
last_impression_ = *(navigation_handle->GetImpression());
num_impressions_++;
if (!waiting_for_null_impression_ &&
num_impressions_ >= expected_num_impressions_) {
impression_loop_.Quit();
}
}
// Waits for |expected_num_impressions_| navigations with impressions, and
// returns the last impression.
const blink::Impression& SourceObserver::Wait() {
if (num_impressions_ >= expected_num_impressions_)
return *last_impression_;
impression_loop_.Run();
return last_impression();
}
bool SourceObserver::WaitForNavigationWithNoImpression() {
waiting_for_null_impression_ = true;
impression_loop_.Run();
waiting_for_null_impression_ = false;
return true;
}
// Builds an impression with default values. This is done as a builder because
// all values needed to be provided at construction time.
SourceBuilder::SourceBuilder(base::Time time)
: source_time_(time),
expiry_(base::Milliseconds(kExpiryTime)),
source_origin_(*SuitableOrigin::Deserialize(kDefaultSourceOrigin)),
destination_origins_(
{*SuitableOrigin::Deserialize(kDefaultDestinationOrigin)}),
reporting_origin_(*SuitableOrigin::Deserialize(kDefaultReportOrigin)) {}
SourceBuilder::~SourceBuilder() = default;
SourceBuilder::SourceBuilder(const SourceBuilder&) = default;
SourceBuilder::SourceBuilder(SourceBuilder&&) = default;
SourceBuilder& SourceBuilder::operator=(const SourceBuilder&) = default;
SourceBuilder& SourceBuilder::operator=(SourceBuilder&&) = default;
SourceBuilder& SourceBuilder::SetExpiry(base::TimeDelta delta) {
expiry_ = delta;
return *this;
}
SourceBuilder& SourceBuilder::SetEventReportWindow(base::TimeDelta delta) {
event_report_window_ = delta;
return *this;
}
SourceBuilder& SourceBuilder::SetAggregatableReportWindow(
base::TimeDelta delta) {
aggregatable_report_window_ = delta;
return *this;
}
SourceBuilder& SourceBuilder::SetSourceEventId(uint64_t source_event_id) {
source_event_id_ = source_event_id;
return *this;
}
SourceBuilder& SourceBuilder::SetSourceOrigin(url::Origin origin) {
auto suitable_origin = SuitableOrigin::Create(std::move(origin));
CHECK(suitable_origin);
return SetSourceOrigin(std::move(*suitable_origin));
}
SourceBuilder& SourceBuilder::SetSourceOrigin(SuitableOrigin origin) {
source_origin_ = std::move(origin);
return *this;
}
SourceBuilder& SourceBuilder::SetDestinationOrigin(url::Origin origin) {
auto suitable_origin = SuitableOrigin::Create(std::move(origin));
CHECK(suitable_origin);
return SetDestinationOrigin(std::move(*suitable_origin));
}
SourceBuilder& SourceBuilder::SetDestinationOrigin(SuitableOrigin origin) {
return SetDestinationOrigins({std::move(origin)});
}
SourceBuilder& SourceBuilder::SetDestinationOrigins(
base::flat_set<SuitableOrigin> origins) {
DCHECK(!origins.empty());
destination_origins_ = std::move(origins);
return *this;
}
SourceBuilder& SourceBuilder::SetReportingOrigin(url::Origin origin) {
auto suitable_origin = SuitableOrigin::Create(std::move(origin));
CHECK(suitable_origin);
return SetReportingOrigin(std::move(*suitable_origin));
}
SourceBuilder& SourceBuilder::SetReportingOrigin(SuitableOrigin origin) {
reporting_origin_ = std::move(origin);
return *this;
}
SourceBuilder& SourceBuilder::SetSourceType(AttributionSourceType source_type) {
source_type_ = source_type;
return *this;
}
SourceBuilder& SourceBuilder::SetPriority(int64_t priority) {
priority_ = priority;
return *this;
}
SourceBuilder& SourceBuilder::SetFilterData(
attribution_reporting::FilterData filter_data) {
filter_data_ = std::move(filter_data);
return *this;
}
SourceBuilder& SourceBuilder::SetDebugKey(absl::optional<uint64_t> debug_key) {
debug_key_ = debug_key;
return *this;
}
SourceBuilder& SourceBuilder::SetAttributionLogic(
StoredSource::AttributionLogic attribution_logic) {
attribution_logic_ = attribution_logic;
return *this;
}
SourceBuilder& SourceBuilder::SetActiveState(
StoredSource::ActiveState active_state) {
active_state_ = active_state;
return *this;
}
SourceBuilder& SourceBuilder::SetSourceId(StoredSource::Id source_id) {
source_id_ = source_id;
return *this;
}
SourceBuilder& SourceBuilder::SetDedupKeys(std::vector<uint64_t> dedup_keys) {
dedup_keys_ = std::move(dedup_keys);
return *this;
}
SourceBuilder& SourceBuilder::SetAggregationKeys(
attribution_reporting::AggregationKeys aggregation_keys) {
aggregation_keys_ = std::move(aggregation_keys);
return *this;
}
SourceBuilder& SourceBuilder::SetAggregatableBudgetConsumed(
int64_t aggregatable_budget_consumed) {
aggregatable_budget_consumed_ = aggregatable_budget_consumed;
return *this;
}
SourceBuilder& SourceBuilder::SetAggregatableDedupKeys(
std::vector<uint64_t> dedup_keys) {
aggregatable_dedup_keys_ = std::move(dedup_keys);
return *this;
}
SourceBuilder& SourceBuilder::SetIsWithinFencedFrame(
bool is_within_fenced_frame) {
is_within_fenced_frame_ = is_within_fenced_frame;
return *this;
}
SourceBuilder& SourceBuilder::SetDebugReporting(bool debug_reporting) {
debug_reporting_ = debug_reporting;
return *this;
}
CommonSourceInfo SourceBuilder::BuildCommonInfo() const {
return CommonSourceInfo(
source_event_id_, source_origin_, destination_origins_, reporting_origin_,
source_time_,
/*expiry_time=*/source_time_ + expiry_,
/*event_report_window_time=*/
event_report_window_
? absl::make_optional(source_time_ + *event_report_window_)
: absl::nullopt,
/*aggregatable_report_window_time=*/
aggregatable_report_window_
? absl::make_optional(source_time_ + *aggregatable_report_window_)
: absl::nullopt,
source_type_, priority_, filter_data_, debug_key_, aggregation_keys_);
}
StorableSource SourceBuilder::Build() const {
return StorableSource(BuildCommonInfo(), is_within_fenced_frame_,
debug_reporting_);
}
StoredSource SourceBuilder::BuildStored() const {
StoredSource source(BuildCommonInfo(), attribution_logic_, active_state_,
source_id_, aggregatable_budget_consumed_);
source.SetDedupKeys(dedup_keys_);
source.SetAggregatableDedupKeys(aggregatable_dedup_keys_);
return source;
}
AttributionTrigger DefaultTrigger() {
return TriggerBuilder().Build();
}
TriggerBuilder::TriggerBuilder()
: destination_origin_(
*SuitableOrigin::Deserialize(kDefaultDestinationOrigin)),
reporting_origin_(*SuitableOrigin::Deserialize(kDefaultReportOrigin)) {}
TriggerBuilder::~TriggerBuilder() = default;
TriggerBuilder::TriggerBuilder(const TriggerBuilder&) = default;
TriggerBuilder::TriggerBuilder(TriggerBuilder&&) = default;
TriggerBuilder& TriggerBuilder::operator=(const TriggerBuilder&) = default;
TriggerBuilder& TriggerBuilder::operator=(TriggerBuilder&&) = default;
TriggerBuilder& TriggerBuilder::SetTriggerData(uint64_t trigger_data) {
trigger_data_ = trigger_data;
return *this;
}
TriggerBuilder& TriggerBuilder::SetEventSourceTriggerData(
uint64_t event_source_trigger_data) {
event_source_trigger_data_ = event_source_trigger_data;
return *this;
}
TriggerBuilder& TriggerBuilder::SetDestinationOrigin(
url::Origin destination_origin) {
auto suitable_origin = SuitableOrigin::Create(std::move(destination_origin));
CHECK(suitable_origin);
return SetDestinationOrigin(std::move(*suitable_origin));
}
TriggerBuilder& TriggerBuilder::SetDestinationOrigin(SuitableOrigin origin) {
destination_origin_ = std::move(origin);
return *this;
}
TriggerBuilder& TriggerBuilder::SetReportingOrigin(
url::Origin reporting_origin) {
auto suitable_origin = SuitableOrigin::Create(std::move(reporting_origin));
CHECK(suitable_origin);
return SetReportingOrigin(std::move(*suitable_origin));
}
TriggerBuilder& TriggerBuilder::SetReportingOrigin(SuitableOrigin origin) {
reporting_origin_ = std::move(origin);
return *this;
}
TriggerBuilder& TriggerBuilder::SetPriority(int64_t priority) {
priority_ = priority;
return *this;
}
TriggerBuilder& TriggerBuilder::SetDedupKey(
absl::optional<uint64_t> dedup_key) {
dedup_key_ = dedup_key;
return *this;
}
TriggerBuilder& TriggerBuilder::SetDebugKey(
absl::optional<uint64_t> debug_key) {
debug_key_ = debug_key;
return *this;
}
TriggerBuilder& TriggerBuilder::SetAggregatableTriggerData(
std::vector<attribution_reporting::AggregatableTriggerData>
aggregatable_trigger_data) {
aggregatable_trigger_data_ = std::move(aggregatable_trigger_data);
return *this;
}
TriggerBuilder& TriggerBuilder::SetAggregatableValues(
attribution_reporting::AggregatableValues aggregatable_values) {
aggregatable_values_ = std::move(aggregatable_values);
return *this;
}
TriggerBuilder& TriggerBuilder::SetAggregatableDedupKey(
absl::optional<uint64_t> aggregatable_dedup_key) {
aggregatable_dedup_key_ = aggregatable_dedup_key;
return *this;
}
TriggerBuilder& TriggerBuilder::SetIsWithinFencedFrame(
bool is_within_fenced_frame) {
is_within_fenced_frame_ = is_within_fenced_frame;
return *this;
}
TriggerBuilder& TriggerBuilder::SetDebugReporting(bool debug_reporting) {
debug_reporting_ = debug_reporting;
return *this;
}
TriggerBuilder& TriggerBuilder::SetAggregationCoordinator(
::aggregation_service::mojom::AggregationCoordinator
aggregation_coordinator) {
aggregation_coordinator_ = aggregation_coordinator;
return *this;
}
AttributionTrigger TriggerBuilder::Build(
bool generate_event_trigger_data) const {
std::vector<attribution_reporting::EventTriggerData> event_triggers;
if (generate_event_trigger_data) {
event_triggers.emplace_back(
trigger_data_, priority_, dedup_key_,
/*filters=*/
AttributionFiltersForSourceType(AttributionSourceType::kNavigation),
/*not_filters=*/attribution_reporting::Filters());
event_triggers.emplace_back(
event_source_trigger_data_, priority_, dedup_key_,
/*filters=*/
AttributionFiltersForSourceType(AttributionSourceType::kEvent),
/*not_filters=*/attribution_reporting::Filters());
}
return AttributionTrigger(
attribution_reporting::TriggerRegistration(
reporting_origin_,
/*filters=*/attribution_reporting::Filters(),
/*not_filters=*/attribution_reporting::Filters(), debug_key_,
aggregatable_dedup_key_,
*attribution_reporting::EventTriggerDataList::Create(
std::move(event_triggers)),
*attribution_reporting::AggregatableTriggerDataList::Create(
aggregatable_trigger_data_),
aggregatable_values_, debug_reporting_, aggregation_coordinator_),
destination_origin_, is_within_fenced_frame_);
}
AttributionInfoBuilder::AttributionInfoBuilder(StoredSource source)
: source_(std::move(source)) {}
AttributionInfoBuilder::~AttributionInfoBuilder() = default;
AttributionInfoBuilder& AttributionInfoBuilder::SetTime(base::Time time) {
time_ = time;
return *this;
}
AttributionInfoBuilder& AttributionInfoBuilder::SetDebugKey(
absl::optional<uint64_t> debug_key) {
debug_key_ = debug_key;
return *this;
}
AttributionInfo AttributionInfoBuilder::Build() const {
return AttributionInfo(source_, time_, debug_key_);
}
ReportBuilder::ReportBuilder(AttributionInfo attribution_info)
: attribution_info_(std::move(attribution_info)),
external_report_id_(DefaultExternalReportID()) {}
ReportBuilder::~ReportBuilder() = default;
ReportBuilder& ReportBuilder::SetTriggerData(uint64_t trigger_data) {
trigger_data_ = trigger_data;
return *this;
}
ReportBuilder& ReportBuilder::SetReportTime(base::Time time) {
report_time_ = time;
return *this;
}
ReportBuilder& ReportBuilder::SetPriority(int64_t priority) {
priority_ = priority;
return *this;
}
ReportBuilder& ReportBuilder::SetExternalReportId(
base::GUID external_report_id) {
external_report_id_ = std::move(external_report_id);
return *this;
}
ReportBuilder& ReportBuilder::SetRandomizedTriggerRate(double rate) {
randomized_trigger_rate_ = rate;
return *this;
}
ReportBuilder& ReportBuilder::SetReportId(
AttributionReport::EventLevelData::Id id) {
report_id_ = id;
return *this;
}
ReportBuilder& ReportBuilder::SetReportId(
AttributionReport::AggregatableAttributionData::Id id) {
aggregatable_attribution_report_id_ = id;
return *this;
}
ReportBuilder& ReportBuilder::SetAggregatableHistogramContributions(
std::vector<AggregatableHistogramContribution> contributions) {
DCHECK(!contributions.empty());
contributions_ = std::move(contributions);
return *this;
}
ReportBuilder& ReportBuilder::SetAggregationCoordinator(
::aggregation_service::mojom::AggregationCoordinator
aggregation_coordinator) {
aggregation_coordinator_ = aggregation_coordinator;
return *this;
}
AttributionReport ReportBuilder::Build() const {
return AttributionReport(
attribution_info_, report_time_, external_report_id_,
/*failed_send_attempts=*/0,
AttributionReport::EventLevelData(trigger_data_, priority_,
randomized_trigger_rate_, report_id_));
}
AttributionReport ReportBuilder::BuildAggregatableAttribution() const {
return AttributionReport(
attribution_info_, report_time_, external_report_id_,
/*failed_send_attempts=*/0,
AttributionReport::AggregatableAttributionData(
contributions_, aggregatable_attribution_report_id_, report_time_,
aggregation_coordinator_));
}
bool operator==(const AttributionTrigger& a, const AttributionTrigger& b) {
const auto tie = [](const AttributionTrigger& t) {
return std::make_tuple(t.registration(), t.destination_origin(),
t.is_within_fenced_frame());
};
return tie(a) == tie(b);
}
bool operator==(const CommonSourceInfo& a, const CommonSourceInfo& b) {
const auto tie = [](const CommonSourceInfo& source) {
return std::make_tuple(
source.source_event_id(), source.source_origin(),
source.destination_origin(), source.reporting_origin(),
source.source_time(), source.expiry_time(),
source.event_report_window_time(),
source.aggregatable_report_window_time(), source.source_type(),
source.priority(), source.filter_data(), source.debug_key(),
source.aggregation_keys());
};
return tie(a) == tie(b);
}
bool operator==(const AttributionInfo& a, const AttributionInfo& b) {
const auto tie = [](const AttributionInfo& attribution_info) {
return std::make_tuple(attribution_info.source, attribution_info.time,
attribution_info.debug_key);
};
return tie(a) == tie(b);
}
bool operator==(const AttributionStorageDelegate::FakeReport& a,
const AttributionStorageDelegate::FakeReport& b) {
const auto tie = [](const AttributionStorageDelegate::FakeReport& r) {
return std::make_tuple(r.trigger_data, r.report_time);
};
return tie(a) == tie(b);
}
bool operator<(const AttributionStorageDelegate::FakeReport& a,
const AttributionStorageDelegate::FakeReport& b) {
const auto tie = [](const AttributionStorageDelegate::FakeReport& r) {
return std::make_tuple(r.trigger_data, r.report_time);
};
return tie(a) < tie(b);
}
bool operator==(const StorableSource& a, const StorableSource& b) {
const auto tie = [](const StorableSource& source) {
return std::make_tuple(source.common_info(),
source.is_within_fenced_frame(),
source.debug_reporting());
};
return tie(a) == tie(b);
}
// Does not compare source IDs, as they are set by the underlying sqlite DB and
// should not be tested.
bool operator==(const StoredSource& a, const StoredSource& b) {
const auto tie = [](const StoredSource& source) {
return std::make_tuple(source.common_info(), source.attribution_logic(),
source.active_state(), source.dedup_keys(),
source.aggregatable_budget_consumed(),
source.aggregatable_dedup_keys());
};
return tie(a) == tie(b);
}
bool operator==(const AggregatableHistogramContribution& a,
const AggregatableHistogramContribution& b) {
const auto tie = [](const AggregatableHistogramContribution& contribution) {
return std::make_tuple(contribution.key(), contribution.value());
};
return tie(a) == tie(b);
}
// Does not compare ID as it is set by the underlying sqlite db and
// should not be tested.
bool operator==(const AttributionReport::EventLevelData& a,
const AttributionReport::EventLevelData& b) {
const auto tie = [](const AttributionReport::EventLevelData& data) {
return std::make_tuple(data.trigger_data, data.priority,
data.randomized_trigger_rate);
};
return tie(a) == tie(b);
}
// Does not compare ID as it is set by the underlying sqlite db and
// should not be tested.
// Also does not compare the assembled report as it is returned by the
// aggregation service from all the other data.
bool operator==(const AttributionReport::AggregatableAttributionData& a,
const AttributionReport::AggregatableAttributionData& b) {
const auto tie =
[](const AttributionReport::AggregatableAttributionData& data) {
return std::make_tuple(data.contributions, data.initial_report_time);
};
return tie(a) == tie(b);
}
// Does not compare source or report IDs, as they are set by the underlying
// sqlite DB and should not be tested.
bool operator==(const AttributionReport& a, const AttributionReport& b) {
const auto tie = [](const AttributionReport& report) {
return std::make_tuple(report.attribution_info(), report.report_time(),
report.external_report_id(),
report.failed_send_attempts(), report.data());
};
return tie(a) == tie(b);
}
bool operator==(const SendResult& a, const SendResult& b) {
const auto tie = [](const SendResult& info) {
return std::make_tuple(info.status, info.network_error,
info.http_response_code);
};
return tie(a) == tie(b);
}
std::ostream& operator<<(std::ostream& out,
AttributionTrigger::EventLevelResult status) {
switch (status) {
case AttributionTrigger::EventLevelResult::kSuccess:
out << "success";
break;
case AttributionTrigger::EventLevelResult::kSuccessDroppedLowerPriority:
out << "successDroppedLowerPriority";
break;
case AttributionTrigger::EventLevelResult::kInternalError:
out << "internalError";
break;
case AttributionTrigger::EventLevelResult::
kNoCapacityForConversionDestination:
out << "insufficientDestinationCapacity";
break;
case AttributionTrigger::EventLevelResult::kNoMatchingImpressions:
out << "noMatchingSources";
break;
case AttributionTrigger::EventLevelResult::kDeduplicated:
out << "deduplicated";
break;
case AttributionTrigger::EventLevelResult::kExcessiveAttributions:
out << "excessiveAttributions";
break;
case AttributionTrigger::EventLevelResult::kPriorityTooLow:
out << "priorityTooLow";
break;
case AttributionTrigger::EventLevelResult::kDroppedForNoise:
out << "noised";
break;
case AttributionTrigger::EventLevelResult::kExcessiveReportingOrigins:
out << "excessiveReportingOrigins";
break;
case AttributionTrigger::EventLevelResult::kNoMatchingSourceFilterData:
out << "noMatchingSourceFilterData";
break;
case AttributionTrigger::EventLevelResult::kProhibitedByBrowserPolicy:
out << "prohibitedByBrowserPolicy";
break;
case AttributionTrigger::EventLevelResult::kNoMatchingConfigurations:
out << "noMatchingConfigurations";
break;
case AttributionTrigger::EventLevelResult::kExcessiveReports:
out << "excessiveReports";
break;
case AttributionTrigger::EventLevelResult::kFalselyAttributedSource:
out << "falselyAttributedSource";
break;
case AttributionTrigger::EventLevelResult::kReportWindowPassed:
out << "reportWindowPassed";
break;
}
return out;
}
std::ostream& operator<<(std::ostream& out,
AttributionTrigger::AggregatableResult status) {
switch (status) {
case AttributionTrigger::AggregatableResult::kSuccess:
out << "success";
break;
case AttributionTrigger::AggregatableResult::kInternalError:
out << "internalError";
break;
case AttributionTrigger::AggregatableResult::
kNoCapacityForConversionDestination:
out << "insufficientDestinationCapacity";
break;
case AttributionTrigger::AggregatableResult::kNoMatchingImpressions:
out << "noMatchingSources";
break;
case AttributionTrigger::AggregatableResult::kExcessiveAttributions:
out << "excessiveAttributions";
break;
case AttributionTrigger::AggregatableResult::kExcessiveReportingOrigins:
out << "excessiveReportingOrigins";
break;
case AttributionTrigger::AggregatableResult::kNoHistograms:
out << "noHistograms";
break;
case AttributionTrigger::AggregatableResult::kInsufficientBudget:
out << "insufficientBudget";
break;
case AttributionTrigger::AggregatableResult::kNoMatchingSourceFilterData:
out << "noMatchingSourceFilterData";
break;
case AttributionTrigger::AggregatableResult::kNotRegistered:
out << "notRegistered";
break;
case AttributionTrigger::AggregatableResult::kProhibitedByBrowserPolicy:
out << "prohibitedByBrowserPolicy";
break;
case AttributionTrigger::AggregatableResult::kDeduplicated:
out << "deduplicated";
break;
case AttributionTrigger::AggregatableResult::kReportWindowPassed:
out << "reportWindowPassed";
break;
}
return out;
}
std::ostream& operator<<(std::ostream& out, RateLimitResult result) {
switch (result) {
case RateLimitResult::kAllowed:
out << "kAllowed";
break;
case RateLimitResult::kNotAllowed:
out << "kNotAllowed";
break;
case RateLimitResult::kError:
out << "kError";
break;
}
return out;
}
std::ostream& operator<<(std::ostream& out,
StoredSource::AttributionLogic attribution_logic) {
switch (attribution_logic) {
case StoredSource::AttributionLogic::kNever:
out << "kNever";
break;
case StoredSource::AttributionLogic::kTruthfully:
out << "kTruthfully";
break;
case StoredSource::AttributionLogic::kFalsely:
out << "kFalsely";
break;
}
return out;
}
std::ostream& operator<<(std::ostream& out,
StoredSource::ActiveState active_state) {
switch (active_state) {
case StoredSource::ActiveState::kActive:
out << "kActive";
break;
case StoredSource::ActiveState::kInactive:
out << "kInactive";
break;
case StoredSource::ActiveState::kReachedEventLevelAttributionLimit:
out << "kReachedEventLevelAttributionLimit";
break;
}
return out;
}
std::ostream& operator<<(std::ostream& out,
const AttributionTrigger& conversion) {
return out << "{registration=" << conversion.registration()
<< ",destination_origin=" << conversion.destination_origin()
<< ",is_within_fenced_frame="
<< conversion.is_within_fenced_frame();
}
std::ostream& operator<<(std::ostream& out, const CommonSourceInfo& source) {
return out << "{source_event_id=" << source.source_event_id()
<< ",source_origin=" << source.source_origin()
<< ",destination_origin=" << source.destination_origin()
<< ",reporting_origin=" << source.reporting_origin()
<< ",source_time=" << source.source_time()
<< ",expiry_time=" << source.expiry_time()
<< ",event_report_window_time="
<< source.event_report_window_time()
<< ",aggregatable_report_window_time="
<< source.aggregatable_report_window_time()
<< ",source_type=" << source.source_type()
<< ",priority=" << source.priority()
<< ",filter_data=" << source.filter_data() << ",debug_key="
<< (source.debug_key() ? base::NumberToString(*source.debug_key())
: "null")
<< ",aggregation_keys=" << source.aggregation_keys() << "}";
}
std::ostream& operator<<(std::ostream& out,
const AttributionInfo& attribution_info) {
return out << "{source=" << attribution_info.source
<< ",time=" << attribution_info.time << ",debug_key="
<< (attribution_info.debug_key
? base::NumberToString(*attribution_info.debug_key)
: "null")
<< "}";
}
std::ostream& operator<<(std::ostream& out,
const AttributionStorageDelegate::FakeReport& r) {
return out << "{trigger_data=" << r.trigger_data
<< ",report_time=" << r.report_time << "}";
}
std::ostream& operator<<(std::ostream& out, const StorableSource& source) {
return out << "{common_info=" << source.common_info()
<< ",is_within_fenced_frame=" << source.is_within_fenced_frame()
<< ",debug_reporting=" << source.debug_reporting() << "}";
}
std::ostream& operator<<(std::ostream& out, const StoredSource& source) {
out << "{common_info=" << source.common_info()
<< ",attribution_logic=" << source.attribution_logic()
<< ",active_state=" << source.active_state()
<< ",source_id=" << *source.source_id()
<< ",aggregatable_budget_consumed="
<< source.aggregatable_budget_consumed() << ",dedup_keys=[";
const char* separator = "";
for (int64_t dedup_key : source.dedup_keys()) {
out << separator << dedup_key;
separator = ", ";
}
out << "],aggregatable_dedup_keys=[";
separator = "";
for (int64_t dedup_key : source.aggregatable_dedup_keys()) {
out << separator << dedup_key;
separator = ",";
}
return out << "]}";
}
std::ostream& operator<<(
std::ostream& out,
const AggregatableHistogramContribution& contribution) {
return out << "{key=" << contribution.key()
<< ",value=" << contribution.value() << "}";
}
std::ostream& operator<<(std::ostream& out,
const AttributionReport::EventLevelData& data) {
return out << "{trigger_data=" << data.trigger_data
<< ",priority=" << data.priority
<< ",randomized_trigger_rate=" << data.randomized_trigger_rate
<< ",id=" << *data.id << "}";
}
std::ostream& operator<<(
std::ostream& out,
const AttributionReport::AggregatableAttributionData& data) {
out << "{contributions=[";
const char* separator = "";
for (const auto& contribution : data.contributions) {
out << separator << contribution;
separator = ", ";
}
return out << "],id=" << *data.id
<< ",initial_report_time=" << data.initial_report_time << "}";
}
namespace {
std::ostream& operator<<(
std::ostream& out,
const absl::variant<AttributionReport::EventLevelData,
AttributionReport::AggregatableAttributionData>& data) {
absl::visit([&out](const auto& v) { out << v; }, data);
return out;
}
} // namespace
std::ostream& operator<<(std::ostream& out, const AttributionReport& report) {
out << "{attribution_info=" << report.attribution_info()
<< ",report_time=" << report.report_time()
<< ",external_report_id=" << report.external_report_id()
<< ",failed_send_attempts=" << report.failed_send_attempts()
<< ",data=" << report.data() << "}";
return out;
}
std::ostream& operator<<(std::ostream& out,
AttributionReport::Type report_type) {
switch (report_type) {
case AttributionReport::Type::kEventLevel:
out << "kEventLevel";
break;
case AttributionReport::Type::kAggregatableAttribution:
out << "kAggregatableAttribution";
break;
}
return out;
}
std::ostream& operator<<(std::ostream& out, SendResult::Status status) {
switch (status) {
case SendResult::Status::kSent:
out << "kSent";
break;
case SendResult::Status::kTransientFailure:
out << "kTransientFailure";
break;
case SendResult::Status::kFailure:
out << "kFailure";
break;
case SendResult::Status::kDropped:
out << "kDropped";
break;
case SendResult::Status::kFailedToAssemble:
out << "kFailedToAssemble";
break;
}
return out;
}
std::ostream& operator<<(std::ostream& out, const SendResult& info) {
return out << "{status=" << info.status
<< ",network_error=" << net::ErrorToShortString(info.network_error)
<< ",http_response_code=" << info.http_response_code << "}";
}
std::ostream& operator<<(std::ostream& out, StorableSource::Result status) {
switch (status) {
case StorableSource::Result::kSuccess:
return out << "success";
case StorableSource::Result::kInternalError:
return out << "internalError";
case StorableSource::Result::kInsufficientSourceCapacity:
return out << "insufficientSourceCapacity";
case StorableSource::Result::kInsufficientUniqueDestinationCapacity:
return out << "insufficientUniqueDestinationCapacity";
case StorableSource::Result::kExcessiveReportingOrigins:
return out << "excessiveReportingOrigins";
case StorableSource::Result::kProhibitedByBrowserPolicy:
return out << "prohibitedByBrowserPolicy";
case StorableSource::Result::kSuccessNoised:
return out << "successNoised";
}
}
EventTriggerDataMatcherConfig::EventTriggerDataMatcherConfig(
::testing::Matcher<uint64_t> data,
::testing::Matcher<int64_t> priority,
::testing::Matcher<absl::optional<uint64_t>> dedup_key,
::testing::Matcher<const attribution_reporting::Filters&> filters,
::testing::Matcher<const attribution_reporting::Filters&> not_filters)
: data(std::move(data)),
priority(std::move(priority)),
dedup_key(std::move(dedup_key)),
filters(std::move(filters)),
not_filters(std::move(not_filters)) {}
EventTriggerDataMatcherConfig::~EventTriggerDataMatcherConfig() = default;
::testing::Matcher<const attribution_reporting::EventTriggerData&>
EventTriggerDataMatches(const EventTriggerDataMatcherConfig& cfg) {
return ::testing::AllOf(
Field("data", &attribution_reporting::EventTriggerData::data, cfg.data),
Field("priority", &attribution_reporting::EventTriggerData::priority,
cfg.priority),
Field("dedup_key", &attribution_reporting::EventTriggerData::dedup_key,
cfg.dedup_key),
Field("filters", &attribution_reporting::EventTriggerData::filters,
cfg.filters),
Field("not_filters",
&attribution_reporting::EventTriggerData::not_filters,
cfg.not_filters));
}
TriggerRegistrationMatcherConfig::TriggerRegistrationMatcherConfig(
::testing::Matcher<const SuitableOrigin&> reporting_origin,
::testing::Matcher<const attribution_reporting::Filters&> filters,
::testing::Matcher<const attribution_reporting::Filters&> not_filters,
::testing::Matcher<absl::optional<uint64_t>> debug_key,
::testing::Matcher<const attribution_reporting::EventTriggerDataList&>
event_triggers,
::testing::Matcher<absl::optional<uint64_t>> aggregatable_dedup_key,
::testing::Matcher<bool> debug_reporting,
::testing::Matcher<
const attribution_reporting::AggregatableTriggerDataList&>
aggregatable_trigger_data,
::testing::Matcher<const attribution_reporting::AggregatableValues&>
aggregatable_values,
::testing::Matcher<::aggregation_service::mojom::AggregationCoordinator>
aggregation_coordinator)
: reporting_origin(std::move(reporting_origin)),
filters(std::move(filters)),
not_filters(std::move(not_filters)),
debug_key(std::move(debug_key)),
event_triggers(std::move(event_triggers)),
aggregatable_dedup_key(std::move(aggregatable_dedup_key)),
debug_reporting(std::move(debug_reporting)),
aggregatable_trigger_data(std::move(aggregatable_trigger_data)),
aggregatable_values(std::move(aggregatable_values)),
aggregation_coordinator(std::move(aggregation_coordinator)) {}
TriggerRegistrationMatcherConfig::~TriggerRegistrationMatcherConfig() = default;
::testing::Matcher<const attribution_reporting::TriggerRegistration&>
TriggerRegistrationMatches(const TriggerRegistrationMatcherConfig& cfg) {
return AllOf(
Field("reporting_origin",
&attribution_reporting::TriggerRegistration::reporting_origin,
cfg.reporting_origin),
Field("filters", &attribution_reporting::TriggerRegistration::filters,
cfg.filters),
Field("not_filters",
&attribution_reporting::TriggerRegistration::not_filters,
cfg.not_filters),
Field("debug_key", &attribution_reporting::TriggerRegistration::debug_key,
cfg.debug_key),
Field("event_triggers",
&attribution_reporting::TriggerRegistration::event_triggers,
cfg.event_triggers),
Field("aggregatable_dedup_key",
&attribution_reporting::TriggerRegistration::aggregatable_dedup_key,
cfg.aggregatable_dedup_key),
Field("debug_reporting",
&attribution_reporting::TriggerRegistration::debug_reporting,
cfg.debug_reporting),
Field("aggregatable_trigger_data",
&attribution_reporting::TriggerRegistration::
aggregatable_trigger_data,
cfg.aggregatable_trigger_data),
Field("aggregatable_values",
&attribution_reporting::TriggerRegistration::aggregatable_values,
cfg.aggregatable_values),
Field(
"aggregation_coordinator",
&attribution_reporting::TriggerRegistration::aggregation_coordinator,
cfg.aggregation_coordinator));
}
AttributionTriggerMatcherConfig::AttributionTriggerMatcherConfig(
::testing::Matcher<const attribution_reporting::TriggerRegistration&>
registration,
::testing::Matcher<const SuitableOrigin&> destination_origin,
::testing::Matcher<bool> is_within_fenced_frame)
: registration(std::move(registration)),
destination_origin(std::move(destination_origin)),
is_within_fenced_frame(std::move(is_within_fenced_frame)) {}
AttributionTriggerMatcherConfig::~AttributionTriggerMatcherConfig() = default;
::testing::Matcher<AttributionTrigger> AttributionTriggerMatches(
const AttributionTriggerMatcherConfig& cfg) {
return AllOf(
Property("registration", &AttributionTrigger::registration,
cfg.registration),
Property("destination_origin", &AttributionTrigger::destination_origin,
cfg.destination_origin),
Property("is_within_fenced_frame",
&AttributionTrigger::is_within_fenced_frame,
cfg.is_within_fenced_frame));
}
std::vector<AttributionReport> GetAttributionReportsForTesting(
AttributionManager* manager) {
base::RunLoop run_loop;
std::vector<AttributionReport> attribution_reports;
manager->GetPendingReportsForInternalUse(
AttributionReport::Types{
AttributionReport::Type::kEventLevel,
AttributionReport::Type::kAggregatableAttribution},
/*limit=*/-1,
base::BindLambdaForTesting([&](std::vector<AttributionReport> reports) {
attribution_reports = std::move(reports);
run_loop.Quit();
}));
run_loop.Run();
return attribution_reports;
}
std::unique_ptr<MockDataHost> GetRegisteredDataHost(
mojo::PendingReceiver<blink::mojom::AttributionDataHost> data_host) {
return std::make_unique<MockDataHost>(std::move(data_host));
}
TestAggregatableSourceProvider::TestAggregatableSourceProvider(size_t size) {
attribution_reporting::AggregationKeys::Keys::container_type keys;
keys.reserve(size);
for (size_t i = 0; i < size; ++i) {
keys.emplace_back(base::NumberToString(i), i);
}
auto source =
attribution_reporting::AggregationKeys::FromKeys(std::move(keys));
DCHECK(source.has_value());
source_ = std::move(*source);
}
TestAggregatableSourceProvider::~TestAggregatableSourceProvider() = default;
SourceBuilder TestAggregatableSourceProvider::GetBuilder(
base::Time source_time) const {
return SourceBuilder(source_time).SetAggregationKeys(source_);
}
TriggerBuilder DefaultAggregatableTriggerBuilder(
const std::vector<uint32_t>& histogram_values) {
std::vector<attribution_reporting::AggregatableTriggerData>
aggregatable_trigger_data;
attribution_reporting::AggregatableValues::Values aggregatable_values;
for (size_t i = 0; i < histogram_values.size(); ++i) {
std::string key_id = base::NumberToString(i);
aggregatable_trigger_data.push_back(
*attribution_reporting::AggregatableTriggerData::Create(
absl::MakeUint128(/*high=*/i, /*low=*/0),
/*source_keys=*/{key_id},
/*filters=*/attribution_reporting::Filters(),
/*not_filters=*/attribution_reporting::Filters()));
aggregatable_values.emplace(std::move(key_id), histogram_values[i]);
}
return TriggerBuilder()
.SetAggregatableTriggerData(std::move(aggregatable_trigger_data))
.SetAggregatableValues(*attribution_reporting::AggregatableValues::Create(
std::move(aggregatable_values)));
}
std::vector<AggregatableHistogramContribution>
DefaultAggregatableHistogramContributions(
const std::vector<uint32_t>& histogram_values) {
std::vector<AggregatableHistogramContribution> contributions;
for (size_t i = 0; i < histogram_values.size(); ++i) {
contributions.emplace_back(absl::MakeUint128(i, i), histogram_values[i]);
}
return contributions;
}
attribution_reporting::Filters AttributionFiltersForSourceType(
AttributionSourceType source_type) {
std::vector<std::string> values;
values.reserve(1);
values.push_back(AttributionSourceTypeToString(source_type));
attribution_reporting::FilterValues filter_values;
filter_values.reserve(1);
filter_values.emplace(attribution_reporting::FilterData::kSourceTypeFilterKey,
std::move(values));
return *attribution_reporting::Filters::Create(std::move(filter_values));
}
} // namespace content