Skip to content

Commit

Permalink
Defer source/trigger JSON parsing to interop execution
Browse files Browse the repository at this point in the history
Instead of parsing registrations during interop-test instantiation, we
defer parsing until the test is being run. This increases the testable
surface area and makes execution more closely resemble the real behavior
of the API, which parses registrations at the time they arrive.

We allow the registrations themselves to be arbitrary JSON, instead of
requiring them to be dictionaries at instantiation time, in order to
further increase the testable surface area.

Change-Id: Ie6d657998c4071167ade30d189e279434ca0b713
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4789905
Reviewed-by: Nan Lin <linnan@chromium.org>
Commit-Queue: Andrew Paseltiner <apaseltiner@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1184742}
  • Loading branch information
Andrew Paseltiner authored and Chromium LUCI CQ committed Aug 17, 2023
1 parent ff45482 commit e3f0944
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 209 deletions.
150 changes: 46 additions & 104 deletions content/browser/attribution_reporting/attribution_interop_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

#include "base/functional/function_ref.h"
#include "base/functional/overloaded.h"
#include "base/logging.h"
#include "base/memory/raw_ref.h"
#include "base/ranges/algorithm.h"
#include "base/strings/string_number_conversions.h"
Expand All @@ -24,16 +23,10 @@
#include "base/types/expected_macros.h"
#include "base/types/optional_util.h"
#include "base/values.h"
#include "components/attribution_reporting/source_registration.h"
#include "components/attribution_reporting/source_registration_error.mojom.h"
#include "components/attribution_reporting/source_type.mojom.h"
#include "components/attribution_reporting/suitable_origin.h"
#include "components/attribution_reporting/test_utils.h"
#include "components/attribution_reporting/trigger_registration.h"
#include "components/attribution_reporting/trigger_registration_error.mojom.h"
#include "content/browser/attribution_reporting/attribution_config.h"
#include "content/browser/attribution_reporting/attribution_trigger.h"
#include "content/browser/attribution_reporting/storable_source.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/abseil-cpp/absl/types/variant.h"

Expand Down Expand Up @@ -124,15 +117,21 @@ class AttributionInteropParser {
if (base::Value* sources = input.Find(kKeySources)) {
auto context = PushContext(kKeySources);
ParseListOfDicts(sources, [&](base::Value::Dict source) {
ParseSource(std::move(source));
ParseRegistration(std::move(source),
/*context_origin_key=*/"source_origin",
/*parse_source_type=*/true,
/*header=*/"Attribution-Reporting-Register-Source");
});
}

static constexpr char kKeyTriggers[] = "triggers";
if (base::Value* triggers = input.Find(kKeyTriggers)) {
auto context = PushContext(kKeyTriggers);
ParseListOfDicts(triggers, [&](base::Value::Dict trigger) {
ParseTrigger(std::move(trigger));
ParseRegistration(std::move(trigger),
/*context_origin_key=*/"destination_origin",
/*parse_source_type=*/false,
/*header=*/"Attribution-Reporting-Register-Trigger");
});
}

Expand Down Expand Up @@ -288,115 +287,58 @@ class AttributionInteropParser {
}
}

void ParseSource(base::Value::Dict source_dict) {
base::Time source_time = ParseDistinctTime(source_dict);
void ParseRegistration(base::Value::Dict dict,
const base::StringPiece context_origin_key,
const bool parse_source_type,
const base::StringPiece header) {
const base::Time time = ParseDistinctTime(dict);

absl::optional<SuitableOrigin> source_origin;
absl::optional<SuitableOrigin> context_origin;
absl::optional<SuitableOrigin> reporting_origin;
absl::optional<SourceType> source_type;

ParseDict(source_dict, kRegistrationRequestKey,
[&](base::Value::Dict dict) {
source_origin = ParseOrigin(dict, "source_origin");
reporting_origin = ParseOrigin(dict, kAttributionSrcUrlKey);
source_type = ParseSourceType(dict);
});

if (has_error_) {
return;
}

auto context = PushContext(kResponsesKey);
ParseListOfDicts(
source_dict.Find(kResponsesKey),
[&](base::Value::Dict dict) {
VerifyReportingOrigin(dict, *reporting_origin);

bool debug_permission = ParseDebugPermission(dict);
ParseDict(dict, kRegistrationRequestKey, [&](base::Value::Dict reg_req) {
context_origin = ParseOrigin(reg_req, context_origin_key);
reporting_origin = ParseOrigin(reg_req, kAttributionSrcUrlKey);

if (has_error_) {
return;
}

ParseDict(dict, kResponseKey, [&](base::Value::Dict response_dict) {
ParseDict(
response_dict, "Attribution-Reporting-Register-Source",
[&](base::Value::Dict registration_dict) {
auto registration =
attribution_reporting::SourceRegistration::Parse(
std::move(registration_dict));
// TODO(apaseltiner): Defer parsing until the intended
// time.
if (!registration.has_value()) {
LOG(WARNING)
<< context_path_ << ": " << registration.error();
return;
}

events_.emplace_back(
StorableSource(std::move(*reporting_origin),
std::move(*registration),
std::move(*source_origin), *source_type,
/*is_within_fenced_frame=*/false),
source_time, debug_permission);
});
});
},
/*expected_size=*/1);
}

void ParseTrigger(base::Value::Dict trigger_dict) {
base::Time trigger_time = ParseDistinctTime(trigger_dict);

absl::optional<SuitableOrigin> destination_origin;
absl::optional<SuitableOrigin> reporting_origin;

ParseDict(trigger_dict, kRegistrationRequestKey,
[&](base::Value::Dict dict) {
destination_origin = ParseOrigin(dict, "destination_origin");
reporting_origin = ParseOrigin(dict, kAttributionSrcUrlKey);
});
if (parse_source_type) {
source_type = ParseSourceType(reg_req);
}
});

if (has_error_) {
return;
}

auto context = PushContext(kResponsesKey);
ParseListOfDicts(
trigger_dict.Find(kResponsesKey),
[&](base::Value::Dict dict) {
VerifyReportingOrigin(dict, *reporting_origin);
dict.Find(kResponsesKey),
[&](base::Value::Dict response) {
VerifyReportingOrigin(response, *reporting_origin);

bool debug_permission = ParseDebugPermission(dict);
const bool debug_permission = ParseDebugPermission(response);

if (has_error_) {
return;
}

ParseDict(dict, kResponseKey, [&](base::Value::Dict response_dict) {
ParseDict(
response_dict, "Attribution-Reporting-Register-Trigger",
[&](base::Value::Dict registration_dict) {
// TODO(apaseltiner): Defer parsing until the intended
// time.
auto registration =
attribution_reporting::TriggerRegistration::Parse(
std::move(registration_dict));
if (!registration.has_value()) {
LOG(WARNING)
<< context_path_ << ": " << registration.error();
return;
}

events_.emplace_back(
AttributionTrigger(std::move(*reporting_origin),
std::move(*registration),
std::move(*destination_origin),
/*verifications=*/{},
/*is_within_fenced_frame=*/false),
trigger_time, debug_permission);
});
});
ParseDict(
response, kResponseKey, [&](base::Value::Dict response_dict) {
auto context = PushContext(header);
absl::optional<base::Value> registration =
response_dict.Extract(header);
if (!registration.has_value()) {
*Error() << "must be present";
return;
}

auto& event = events_.emplace_back(std::move(*reporting_origin),
std::move(*context_origin));
event.source_type = source_type;
event.registration = std::move(*registration);
event.time = time;
event.debug_permission = debug_permission;
});
},
/*expected_size=*/1);
}
Expand Down Expand Up @@ -603,10 +545,10 @@ class AttributionInteropParser {
} // namespace

AttributionSimulationEvent::AttributionSimulationEvent(
absl::variant<StorableSource, AttributionTrigger> event,
base::Time time,
bool debug_permission)
: event(std::move(event)), time(time), debug_permission(debug_permission) {}
SuitableOrigin reporting_origin,
SuitableOrigin context_origin)
: reporting_origin(std::move(reporting_origin)),
context_origin(std::move(context_origin)) {}

AttributionSimulationEvent::~AttributionSimulationEvent() = default;

Expand Down
19 changes: 11 additions & 8 deletions content/browser/attribution_reporting/attribution_interop_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,26 @@
#include "base/time/time.h"
#include "base/types/expected.h"
#include "base/values.h"
#include "content/browser/attribution_reporting/attribution_trigger.h"
#include "content/browser/attribution_reporting/storable_source.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
#include "components/attribution_reporting/source_type.mojom-forward.h"
#include "components/attribution_reporting/suitable_origin.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

namespace content {

struct AttributionConfig;

struct AttributionSimulationEvent {
absl::variant<StorableSource, AttributionTrigger> event;
attribution_reporting::SuitableOrigin reporting_origin;
attribution_reporting::SuitableOrigin context_origin;
// If null, the event represents a trigger. Otherwise, represents a source.
absl::optional<attribution_reporting::mojom::SourceType> source_type;
base::Value registration;
base::Time time;
bool debug_permission;
bool debug_permission = false;

AttributionSimulationEvent(
absl::variant<StorableSource, AttributionTrigger> event,
base::Time time,
bool debug_permission);
attribution_reporting::SuitableOrigin reporting_origin,
attribution_reporting::SuitableOrigin context_origin);

~AttributionSimulationEvent();

Expand Down

0 comments on commit e3f0944

Please sign in to comment.