Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 13 additions & 141 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -691,38 +691,6 @@ a [=report window=] [=struct=] with the following fields:
[=report windows=], because there are no gaps in time between any of the
[=report windows|windows=].

<h3 id="summary-operator-header">Summary operator</h3>

A <dfn>summary operator</dfn> summarizes the triggers attributed to an
[=attribution source=]. Its value is one of the following:

<dl dfn-for="summary operator">
: "<dfn><code>count</code></dfn>"
:: Number of triggers attributed.
: "<dfn><code>value_sum</code></dfn>"
:: Sum of the value of triggers.

</dl>

<h3 id="summary-bucket-header">Summary bucket</h3>

A <dfn>summary bucket</dfn> is a [=struct=] with the following items:

<dl dfn-for="summary bucket">
: <dfn>start</dfn>
:: An unsigned 32-bit integer.
: <dfn>end</dfn>
:: An unsigned 32-bit integer.

</dl>

A <dfn>summary bucket list</dfn> is a [=list=] of [=summary buckets=].
It has the following constraints:

* Elements are strictly in ascending order based on their [=summary bucket/start=].
* Every element's [=summary bucket/end=] is equal to the next element's [=summary bucket/start=] - 1, if it exists.
* There is at least one element in the list.

<h3 id="trigger-data-matching-mode-header">Trigger-data matching mode</h3>

A <dfn>trigger-data matching mode</dfn> is one of the following:
Expand Down Expand Up @@ -969,8 +937,6 @@ An event-level trigger configuration is a [=struct=] with the following items:
:: A [=list=] of [=filter configs=].
: <dfn>negated filters</dfn>
:: A [=list=] of [=filter configs=].
: <dfn>value</dfn>
:: A positive unsigned 32-bit integer.

</dl>

Expand Down Expand Up @@ -2437,11 +2403,8 @@ A <dfn>source-registration JSON key</dfn> is one of the following:
<li>"<dfn><code>priority</code></dfn>"
<li>"<dfn><code>source_event_id</code></dfn>"
<li>"<dfn><code>start_time</code></dfn>"
<li>"<dfn><code>summary_buckets</code></dfn>"
<li>"<dfn><code>summary_operator</code></dfn>"
<li>"<dfn><code>trigger_data</code></dfn>"
<li>"<dfn><code>trigger_data_matching</code></dfn>"
<li>"<dfn><code>trigger_specs</code></dfn>"
<li>"<dfn><code>values</code></dfn>"
</ul>

Expand Down Expand Up @@ -2594,56 +2557,12 @@ To <dfn>parse report windows</dfn> given a |value|, a
1. Set |startDuration| to |endDuration|.
1. Return |windows|.

The user-agent has an associated boolean
<dfn>experimental Flexible Event support</dfn> (default false) that exposes
non-normative behavior described in the
<a href="https://github.com/WICG/attribution-reporting-api/blob/main/flexible_event_config.md">Flexible event-level configurations</a>
proposal.

To <dfn>parse summary operator</dfn> given a [=map=] |map|:

1. Let |value| be "<code>[=summary operator/count=]</code>".
1. If |map|["<code>[=source-registration JSON key/summary_operator=]</code>"] [=map/exists=]:
1. If |map|["<code>[=source-registration JSON key/summary_operator=]</code>"] is not a [=string=], return an
error.
1. If |map|["<code>[=source-registration JSON key/summary_operator=]</code>"] is not a
[=summary operator=], return an error.
1. Set |value| to |map|["<code>[=source-registration JSON key/summary_operator=]</code>"].
1. Return |value|.

To <dfn>parse summary buckets</dfn> given a [=map=] |map| and an integer |maxEventLevelReports|:

1. Let |values| be [=the inclusive range|the range=] 1 to
|maxEventLevelReports|, inclusive.
1. If |map|["<code>[=source-registration JSON key/summary_buckets=]</code>"] [=map/exists=]:
1. If |map|["<code>[=source-registration JSON key/summary_buckets=]</code>"] is not a [=list=], [=list/is empty=], or
its [=list/size=] is greater than |maxEventLevelReports|, return an
error.
1. Set |values| to |map|["<code>[=source-registration JSON key/summary_buckets=]</code>"].
1. Let |prev| be 0.
1. Let |summaryBuckets| be a new [=list=].
1. [=list/iterate|For each=] |item| of |values|:
1. If |item| is not an integer or cannot be represented by an unsigned
32-bit integer, or is less than or equal to |prev|, return an error.
1. Let |summaryBucket| be a new [=summary bucket=] whose items are

: [=summary bucket/start=]
:: |prev|
: [=summary bucket/end=]
:: |item| - 1

1. [=list/Append=] |summaryBucket| to |summaryBuckets|.
1. Set |prev| to |item|.
1. Return |summaryBuckets|.

To <dfn>parse trigger data into a trigger spec map</dfn> given a
|triggerDataList|, a [=trigger spec=] |spec|, a [=trigger spec map=]
|specs|, and a [=boolean=] |allowEmpty|:
|triggerDataList|, a [=trigger spec=] |spec|, and a [=trigger spec map=]
|specs|:

1. If |triggerDataList| is not a [=list=] or its [=list/size=] is greater than
[=max distinct trigger data per source=], return false.
1. If |allowEmpty| is false and |triggerDataList| [=list/is empty=], return
false.
1. [=list/iterate|For each=] |triggerData| of |triggerDataList|:
1. If |triggerData| is not an integer or cannot be represented by an
unsigned 32-bit integer, or |specs|[|triggerData|] [=map/exists=],
Expand All @@ -2662,55 +2581,26 @@ To <dfn>parse trigger specs</dfn> given a [=map=] |map|, a [=moment=]
and |expiry|.
1. If |defaultReportWindows| is an error, return an error.
1. Let |specs| be a new [=trigger spec map=].
1. If [=experimental Flexible Event support=] is true and
|map|["<code>[=source-registration JSON key/trigger_specs=]</code>"] [=map/exists=]:
1. If |map|["<code>[=source-registration JSON key/trigger_data=]</code>"] [=map/exists=], return an error.
1. If |map|["<code>[=source-registration JSON key/trigger_specs=]</code>"] is not a [=list=] or its
[=list/size=] is greater than [=max distinct trigger data per source=],
1. Let |spec| be a new [=trigger spec=] with the following items:
: [=trigger spec/event-level report windows=]
:: |defaultReportWindows|
1. If |map|["<code>[=source-registration JSON key/trigger_data=]</code>"] [=map/exists=]:
1. If the result of running
[=parse trigger data into a trigger spec map=] with
|map|["<code>[=source-registration JSON key/trigger_data=]</code>"], |spec|, and |specs| is false,
return an error.
1. [=list/iterate|For each=] |item| of |map|["<code>[=source-registration JSON key/trigger_specs=]</code>"]:
1. If |item| is not a [=map=], return an error.
1. Let |spec| be a new [=trigger spec=] with the following items:
: [=trigger spec/event-level report windows=]
:: |defaultReportWindows|
1. If |item|["<code>[=source-registration JSON key/event_report_windows=]</code>"] [=map/exists=]:
1. Let |reportWindows| be the result of
[=parsing report windows=] with |item|["<code>[=source-registration JSON key/event_report_windows=]</code>"],
|sourceTime|, and |expiry|.
1. If |reportWindows| is an error, return it.
1. Set |spec|'s [=trigger spec/event-level report windows=] to
|reportWindows|.
1. If |item|["<code>[=source-registration JSON key/trigger_data=]</code>"] does not [=map/exist=], return an error.
1. Let |allowEmpty| be false.
1. If the result of running
[=parse trigger data into a trigger spec map=] with
|item|["<code>[=source-registration JSON key/trigger_data=]</code>"], |spec|, |specs|, and |allowEmpty| is
false, return an error.
1. Otherwise:
1. Let |spec| be a new [=trigger spec=] with the following items:
: [=trigger spec/event-level report windows=]
:: |defaultReportWindows|
1. If |map|["<code>[=source-registration JSON key/trigger_data=]</code>"] [=map/exists=]:
1. Let |allowEmpty| be true.
1. If the result of running
[=parse trigger data into a trigger spec map=] with
|map|["<code>[=source-registration JSON key/trigger_data=]</code>"], |spec|, |specs|, and |allowEmpty| is false,
return an error.
1. Otherwise:
1. [=set/iterate|For each=] integer |triggerData| of
[=the exclusive range|the range=] 0 to
[=default trigger data cardinality=][|sourceType|], exclusive:
1. [=map/Set=] |specs|[|triggerData|] to |spec|.
1. [=set/iterate|For each=] integer |triggerData| of
[=the exclusive range|the range=] 0 to
[=default trigger data cardinality=][|sourceType|], exclusive:
1. [=map/Set=] |specs|[|triggerData|] to |spec|.
1. If |matchingMode| is "<code>[=trigger-data matching mode/modulus=]</code>":
1. Let |i| be 0.
1. [=map/iterate|For each=] |triggerData| of |specs|'s [=map/get the keys|keys=]:
1. If |triggerData| does not equal |i|, return an error.
1. Set |i| to |i| + 1.
1. Return |specs|.

Issue: Invoke [=parse summary buckets=] and [=parse summary operator=]
from this algorithm.

To <dfn>parse a source aggregatable debug reporting config</dfn> given |value|, a
non-negative integer |defaultBudget|, and an [=aggregatable debug reporting config=]
|defaultConfig|:
Expand Down Expand Up @@ -3471,15 +3361,6 @@ A <dfn>trigger-registration JSON key</dfn> is one of the following:

<h3 algorithm id="attribution-trigger-creation">Creating an attribution trigger</h3>

To <dfn>parse an event-trigger value</dfn> given a [=map=] |map|:

1. If [=experimental Flexible Event support=] is false or |map|["<code>[=trigger-registration JSON key/value=]</code>"] does
not [=map/exists|exist=], return 1.
1. Let |value| be |map|["<code>[=trigger-registration JSON key/value=]</code>"].
1. If |value| is not an integer, cannot be represented by an unsigned 32-bit
integer, or is less than or equal to zero, return an error.
1. Return |value|.

To <dfn>parse event triggers</dfn> given a [=map=] |map|:

1. Let |eventTriggers| be a new [=set=].
Expand All @@ -3504,9 +3385,6 @@ To <dfn>parse event triggers</dfn> given a [=map=] |map|:
1. Let |filterPair| be the result of running [=parse a filter pair=] with
|value|.
1. If |filterPair| is an error, return it.
1. Let |triggerValue| be the result of running
[=parse an event-trigger value=] with |value|.
1. If |triggerValue| is an error, return it.
1. Let |eventTrigger| be a new [=event-level trigger configuration=] with
the items:
: [=event-level trigger configuration/trigger data=]
Expand All @@ -3519,8 +3397,6 @@ To <dfn>parse event triggers</dfn> given a [=map=] |map|:
:: |filterPair|[0]
: [=event-level trigger configuration/negated filters=]
:: |filterPair|[1]
: [=event-level trigger configuration/value=]
:: |triggerValue|
1. [=set/Append=] |eventTrigger| to |eventTriggers|.
1. Return |eventTriggers|.

Expand Down Expand Up @@ -4107,10 +3983,6 @@ To <dfn>maybe replace event-level report</dfn> given an [=attribution source=]
1. [=set/Remove=] |rateLimitRecord| from the [=attribution rate-limit cache=].
1. Return "<code>[=event-level-report-replacement result/add-new-report=]</code>".

Issue: This algorithm is not compatible with the behavior proposed for
[=experimental Flexible Event support=] with differing
[=trigger spec/event-level report windows=] for a given source.

To <dfn>trigger event-level attribution</dfn> given an [=attribution trigger=] |trigger| and an
[=attribution source=] |sourceToAttribute|, run the following steps:

Expand Down
11 changes: 4 additions & 7 deletions ts/src/flexible-event/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ if (options.json_file !== undefined) {
const [{ errors, warnings }, source] = validateSource(json, {
vsv: vsv.Chromium,
sourceType: options.source_type,
fullFlex: true,
})
warnings.forEach((i) => logIssue('W', i))
if (errors.length > 0) {
Expand All @@ -114,12 +113,10 @@ if (options.json_file !== undefined) {
new Config(
source.maxEventLevelReports,
source.attributionScopes,
source.triggerSpecs.flatMap((spec) =>
new Array<PerTriggerDataConfig>(spec.triggerData.size).fill(
new PerTriggerDataConfig(
spec.eventReportWindows.endTimes.length,
spec.summaryBuckets.length
)
new Array<PerTriggerDataConfig>(source.triggerData.size).fill(
new PerTriggerDataConfig(
source.eventReportWindows.endTimes.length,
source.maxEventLevelReports
)
)
)
Expand Down
1 change: 0 additions & 1 deletion ts/src/header-validator/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ <h1>Attribution Reporting Header Validation</h1>
<p><label><input type=radio name=header value=eligible><code>Attribution-Reporting-Eligible</code></label>
<p><label><input type=radio name=header value=info><code>Attribution-Reporting-Info</code></label>
<p><label><input type=checkbox checked disabled>Use Chromium's vendor-specific values</label> <a href="https://github.com/WICG/attribution-reporting-api/blob/main/params/chromium-params.md" target=_blank>(details)</a>
<p><label><input type=checkbox name=flex>Enable experimental Flexible Event fields</label> <a href="https://github.com/WICG/attribution-reporting-api/blob/main/flexible_event_config.md" target=_blank>(details)</a>
</fieldset>
<fieldset id=output>
<legend>Validation Result</legend>
Expand Down
11 changes: 0 additions & 11 deletions ts/src/header-validator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,34 +22,27 @@ const sourceTypeFieldset =
document.querySelector<HTMLFieldSetElement>('#source-type')!
const effective = document.querySelector('#effective')!

const flexCheckbox = form.elements.namedItem('flex') as HTMLInputElement

function sourceType(): SourceType {
return parseSourceType(sourceTypeRadios.value)
}

function validate(): void {
sourceTypeFieldset.disabled = true
flexCheckbox.disabled = true

let v: validator.Validator<unknown>

switch (headerRadios.value) {
case 'source':
sourceTypeFieldset.disabled = false
flexCheckbox.disabled = false
v = source.validator({
vsv: vsv.Chromium,
sourceType: sourceType(),
fullFlex: flexCheckbox.checked,
noteInfoGain: true,
})
break
case 'trigger':
flexCheckbox.disabled = false
v = trigger.validator({
vsv: vsv.Chromium,
fullFlex: flexCheckbox.checked,
})
break
case 'os-source':
Expand Down Expand Up @@ -99,8 +92,6 @@ document.querySelector('#linkify')!.addEventListener('click', () => {
url.searchParams.set('source-type', sourceType())
}

url.searchParams.set('flex', flexCheckbox.checked.toString())

void navigator.clipboard.writeText(url.toString())
})

Expand Down Expand Up @@ -136,6 +127,4 @@ if (st !== null && st in SourceType) {
}
sourceTypeRadios.value = st

flexCheckbox.checked = params.get('flex') === 'true'

validate()
8 changes: 0 additions & 8 deletions ts/src/header-validator/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ interface Arguments {
input?: string
file?: string

fullFlex: boolean
sourceType?: SourceType

silent: boolean
Expand Down Expand Up @@ -43,11 +42,6 @@ const options = parse<Arguments>(
'If present, parse input as a source. Otherwise, parse as a trigger.',
},

fullFlex: {
type: Boolean,
description: 'If true, parse experimental Full Flexible Event fields.',
},

silent: {
type: Boolean,
description: 'If true, suppress output.',
Expand Down Expand Up @@ -94,11 +88,9 @@ const out = validate<unknown>(
options.sourceType === undefined
? trigger.validator({
vsv: vsv.Chromium,
fullFlex: options.fullFlex,
})
: source.validator({
vsv: vsv.Chromium,
fullFlex: options.fullFlex,
sourceType: options.sourceType,
})
)
Expand Down
Loading
Loading