From 6a827bd51fe319b0ec347ca0dc98f0ec0d3b55bb Mon Sep 17 00:00:00 2001 From: qingxinwu <6334674+qingxinwu@users.noreply.github.com> Date: Tue, 12 Sep 2023 13:04:27 -0400 Subject: [PATCH] Spec: macro reporting support (#762) * Spec out 3pat macro reporting. Added allowedReportingOrigins field to IG. Added a new registerAdMacro() API that can be called in reportWin(). * Finish specing 3pat macro reporting. Protected audience side. Added a todo to pass macro map to fenced frame reporting function defined in fenced frame spec. * cleanup. * Pass allowed reporting origins through. * Address comments. Link to definitions. --------- Co-authored-by: Qingxin Wu --- spec.bs | 116 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 88 insertions(+), 28 deletions(-) diff --git a/spec.bs b/spec.bs index 574b0c105..133099ecc 100644 --- a/spec.bs +++ b/spec.bs @@ -129,8 +129,10 @@ partial interface Navigator { dictionary AuctionAd { required USVString renderURL; any metadata; + USVString buyerReportingId; USVString buyerAndSellerReportingId; + sequence allowedReportingOrigins; }; dictionary GenerateBidInterestGroup { @@ -279,6 +281,16 @@ This is detectable because it can change the set of fields that are read from th |igAd|'s [=interest group ad/buyer reporting ID=] to it. 1. If |ad|["{{AuctionAd/buyerAndSellerReportingId}}"] [=map/exists=], then set |igAd|'s [=interest group ad/buyer and seller reporting ID=] to it. + 1. If |ad|["{{AuctionAd/allowedReportingOrigins}}"] [=map/exists=]: + 1. Let |allowedReportingOrigins| be a new [=list=] of [=origins=]. + 1. [=list/For each=] |originStr| in |ad|["{{AuctionAd/allowedReportingOrigins}}"]: + 1. Let |origin| be the result of [=parsing an origin=] on |originStr|. + 1. If |origin| is failure, or its [=url/scheme=] is not "`https`", [=exception/throw=] a + {{TypeError}}. + 1. [=list/Append=] |origin| to |allowedReportingOrigins|. + 1. If [=list/size=] of |allowedReportingOrigins| is greater than 10, [=exception/throw=] + a {{TypeError}}. + 1. Set |igAd|'s [=interest group ad/allowed reporting origins=] to |allowedReportingOrigins|. 1. [=list/Append=] |igAd| to |interestGroup|'s |interestGroupField|. 1. If |interestGroup|'s [=interest group/estimated size=] is greater than 50 KB, then [=exception/throw=] a {{TypeError}}. @@ -323,7 +335,6 @@ The estimated size of an [=interest group=] |ig| [=interest group/priority signals overrides=]: 1. The [=string/length=] of |key|. 1. 8 bytes, which is the size of |value|. -1. The size of [=interest group/execution mode=]. 1. The [=string/length=] of the [=URL serializer|serialization=] of |ig|'s [=interest group/bidding url=], if the field is not null. 1. The [=string/length=] of the [=URL serializer|serialization=] of |ig|'s @@ -340,7 +351,11 @@ The estimated size of an [=interest group=] |ig| [=interest group ad/render url=]. 1. The [=string/length=] of |ad|'s [=interest group ad/metadata=] if the field is not null. 1. The [=string/length=] of |ad|'s [=interest group ad/buyer reporting ID=] if the field is not null. - 1. The [=string/length=] of |ad|'s [=interest group ad/buyer and seller reporting ID=] if the field is not null. + 1. The [=string/length=] of |ad|'s [=interest group ad/buyer and seller reporting ID=] if the + field is not null. + 1. If |ad|'s [=interest group ad/allowed reporting origins=] is not null, [=list/for each=] + |origin| of it: + 1. The [=string/length=] of the [=serialization of an origin|serialization=] of |origin|. 1. If |ig|'s [=interest group/ad components=] is not null, [=list/for each=] |ad| of it: 1. The [=string/length=] of the [=URL serializer|serialization=] of |ad|'s [=interest group ad/render url=]. @@ -724,14 +739,22 @@ To asynchronously finish reporting given a 1. [=iteration/While=]: 1. If |buyerDone|, |sellerDone|, and |componentSellerDone| are all true, then [=iteration/break=]. - 1. Wait until |leadingBidInfo|'s [=leading bid info/buyer reporting result=] is not null, - or |leadingBidInfo|'s [=leading bid info/seller reporting result=] is not null, or - |leadingBidInfo|'s [=leading bid info/component seller reporting result=] is not null. + 1. Wait until one of the following fields of |leadingBidInfo| being not null: + * [=leading bid info/buyer reporting result=]; + * [=leading bid info/seller reporting result=]; + * [=leading bid info/component seller reporting result=]. 1. If |buyerDone| is false and |leadingBidInfo|'s [=leading bid info/buyer reporting result=] is not null: 1. Let |buyerMap| be |leadingBidInfo|'s [=leading bid info/buyer reporting result=]'s [=reporting result/reporting beacon map=]. 1. If |buyerMap| is null, set |buyerMap| to an empty [=map=] «[]». + 1. Let |allowedReportingOrigins| be |leadingBidInfo|'s [=leading bid info/leading bid=]'s + [=generated bid/bid ad=]'s [=interest group ad/allowed reporting origins=]. + 1. Let |macroMap| be |leadingBidInfo|'s [=leading bid info/buyer reporting result=]'s + [=reporting result/reporting macro map=]. + 1. TODO: Pass |macroMap| and |allowedReportingOrigins| to [=Finalize a reporting destination=] + when it is updated to take the parameters. May need to convert |macroMap| to a list, based + on what that function expects. 1. [=Finalize a reporting destination=] with |reportingMap|, {{FenceReportingDestination/buyer}}, and |buyerMap|. 1. [=Send report=] to |leadingBidInfo|'s [=leading bid info/buyer reporting result=]'s @@ -1261,9 +1284,9 @@ To generate and score bids given an [=auction config=] |auctionConfig 1. If |originalAds| is not null: 1. Set |ig|'s [=interest group/ads=] to a new [=list=] of [=interest group ad=]. 1. [=list/For each=] |ad| in |originalAds|: - 1. If [=query ad k-anonymity count=] given |ig| and |ad|'s - [=interest group ad/render url=] returns true, [=list/append=] |ad| to |ig|'s - [=interest group/ads=]. + 1. If [=query ad k-anonymity count=] given |ig| and |ad|'s + [=interest group ad/render url=] returns true, [=list/append=] |ad| to |ig|'s + [=interest group/ads=]. 1. Let |originalAdComponents| be |ig|'s [=interest group/ad components=]. 1. If |originalAdComponents| is not null: 1. Set |ig|'s [=interest group/ad components=] to a new [=list=] of [=interest group ad=]. @@ -1867,7 +1890,7 @@ null |winningComponentConfig|: 1. [=map/Set=] |browserSignals|["{{ReportingBrowserSignals/buyerAndSellerReportingId}}"] to |igAd|'s [=interest group ad/buyer and seller reporting ID=]. 1. Let |sellerReportingScript| be the result of [=fetching script=] with |config|'s [=auction config/decision logic url=]. - 1. Let « |sellerSignals|, |reportUrl|, |reportingBeaconMap| » be the result of + 1. Let « |sellerSignals|, |reportUrl|, |reportingBeaconMap|, ignored » be the result of [=evaluating a reporting script=] with |sellerReportingScript|, "`reportResult`", and « |config|'s [=auction config/config idl=], |browserSignals| ». 1. Let |reportingResult| be a [=reporting result=] with the following [=struct/items=]: @@ -1932,8 +1955,8 @@ and a {{ReportingBrowserSignals}} |browserSignals|: 1. Otherwise, [=map/Set=] |reportWinBrowserSignals|["{{ReportWinBrowserSignals/interestGroupName}}"] to |winner|'s [=generated bid/interest group=] [=interest group/name=]. 1. Let |buyerReportingScript| be the result of [=fetching script=] with |winner|'s [=generated bid/interest group=]'s [=interest group/bidding url=]. - 1. Let « ignored, |resultUrl|, |reportingBeaconMap| » be the result of [=evaluating a - reporting script=] with |buyerReportingScript|, "`reportWin`", and + 1. Let « ignored, |resultUrl|, |reportingBeaconMap|, |reportingMacroMap| » be the result of + [=evaluating a reporting script=] with |buyerReportingScript|, "`reportWin`", and « |leadingBidInfo|'s [=leading bid info/auction config=]'s [=auction config/config idl=]'s {{AuctionAdConfig/auctionSignals}}, |perBuyerSignalsForBuyer|, |sellerSignals|, |reportWinBrowserSignals| ». @@ -1944,6 +1967,9 @@ and a {{ReportingBrowserSignals}} |browserSignals|: : [=reporting result/reporting beacon map=] :: |reportingBeaconMap| + + : [=reporting result/reporting macro map=] + :: |reportingMacroMap| # K-anonymity # {#k-anonymity} @@ -2279,8 +2305,10 @@ of the following global objects: exception was [=exception/thrown=] in the previous step, keep |resultJSON| as "null". 1. Let |reportURL| be |global|'s [=InterestGroupReportingScriptRunnerGlobalScope/report url=] 1. If |reportURL| is failure, set |reportURL| to null. + 1. Let |macroMap| be |global|'s [=InterestGroupReportingScriptRunnerGlobalScope/reporting macro map=] + if |functionName| is "`reportWin`", null otherwise. 1. Return « |resultJSON|, |reportURL|, - |global|'s [=InterestGroupReportingScriptRunnerGlobalScope/reporting beacon map=] ». + |global|'s [=InterestGroupReportingScriptRunnerGlobalScope/reporting beacon map=], |macroMap| ».
@@ -2433,13 +2461,15 @@ To convert GenerateBidOutput to generated bid given a {{GenerateBidOu 1. Let |adUrl| be the result of running the [=URL parser=] on |generateBidOutput|["{{GenerateBidOutput/render}}"]. 1. If |adUrl| is failure, return failure. - 1. If [=validating an ad url=] given |adUrl|, |ig|, and false returns false, return failure. 1. Set |adDescriptor|'s [=ad descriptor/url=] to |adUrl|. 1. Otherwise: 1. Set |adDescriptor| to the result of [=converting an ad render=] given - |generateBidOutput|["{{GenerateBidOutput/render}}"], |ig| and false. + |generateBidOutput|["{{GenerateBidOutput/render}}"]. 1. If |adDescriptor| is failure, return failure. + 1. Let |bidAd| be the result of [=finding matching ad=] given |adDescriptor|, |ig|, and false. + 1. If |bidAd| is null, return failure. 1. Set |bid|'s [=generated bid/ad descriptor=] to |adDescriptor|. + 1. Set |bid|'s [=generated bid/bid ad=] to |bidAd|. 1. If |generateBidOutput|["{{GenerateBidOutput/adComponents}}"] [=map/exists=]: 1. Let |adComponents| be |generateBidOutput|["{{GenerateBidOutput/adComponents}}"]. 1. Return failure if any of the following conditions hold: @@ -2451,12 +2481,11 @@ To convert GenerateBidOutput to generated bid given a {{GenerateBidOu 1. If |component| is {{DOMString}}: 1. Let |componentUrl| be the result of running the [=URL parser=] on |component|. 1. If |componentUrl| is failure, return failure. - 1. If [=validating an ad url=] given |componentUrl|, |ig|, and true returns false, return failure. 1. Set |componentDescriptor|'s [=ad descriptor/url=] to |componentUrl|. 1. Otherwise: - 1. Set |componentDescriptor| to the result of [=converting an ad render=] given |component|, |ig|, - and true. + 1. Set |componentDescriptor| to the result of [=converting an ad render=] given |component|. 1. If |componentDescriptor| is failure, return failure. + 1. If [=finding matching ad=] given |componentUrl|, |ig|, and true returns null, return failure. 1. [=list/Append=] |componentDescriptor| to |adComponentDescriptors|. 1. Set |bid|'s [=generated bid/ad component descriptors=] to |adComponentDescriptors|. 1. If |generateBidOutput|["{{GenerateBidOutput/adCost}}"] [=map/exists=]: @@ -2490,12 +2519,10 @@ To convert GenerateBidOutput to generated bid given a {{GenerateBidOu
- To convert an ad render given an {{AdRender}} |adRender|, an [=interest group=] |ig|, - and a [=boolean=] |isComponent|: + To convert an ad render given an {{AdRender}} |adRender|: 1. Let |adUrl| be the result of running the [=URL parser=] on |adRender|["{{AdRender/url}}"]. 1. If |adUrl| is failure, return failure. - 1. If [=validating an ad url=] given |adUrl|, |ig|, and |isComponent| returns false, return failure. 1. Let |adDescriptor| be a new [=ad descriptor=]. 1. Set |adDescriptor|'s [=ad descriptor/url=] to |adUrl|. 1. If |adRender|["{{AdRender/width}}"] [=map/exists=]: @@ -2514,17 +2541,19 @@ To convert GenerateBidOutput to generated bid given a {{GenerateBidOu
- To validate an ad url given a [=URL=] |adUrl|, an [=interest group=] |ig|, and a - [=boolean=] |isComponent|: + To find matching ad given an [=ad descriptor=] |adDescriptor|, an [=interest group=] + |ig|, and a [=boolean=] |isComponent|: - 1. If |adUrl|'s [=url/scheme=] is not "`https`", return false. + 1. Let |adUrl| be |adDescriptor|'s [=ad descriptor/url=]. + 1. If |adUrl|'s [=url/scheme=] is not "`https`", return null. + 1. TODO: Need to check [=ad descriptor/size=] as well. 1. If |isComponent|: 1. [=list/For each=] |ad| in |ig|'s [=interest group/ad components=]: - 1. If |ad|'s [=interest group ad/render url=] equals |adUrl|, return true. + 1. If |ad|'s [=interest group ad/render url=] equals |adUrl|, return |ad|. 1. Otherwise: 1. [=list/For each=] |ad| in |ig|'s [=interest group/ads=]: - 1. If |ad|'s [=interest group ad/render url=] equals |adUrl|, return true. - 1. Return false. + 1. If |ad|'s [=interest group ad/render url=] equals |adUrl|, return |ad|. + 1. Return null.
@@ -2590,10 +2619,14 @@ interface InterestGroupReportingScriptRunnerGlobalScope : InterestGroupScriptRunnerGlobalScope { undefined sendReportTo(DOMString url); undefined registerAdBeacon(record<DOMString, USVString> map); + undefined registerAdMacro(DOMString name, USVString value); }; +Note: {{InterestGroupReportingScriptRunnerGlobalScope/registerAdMacro(name, value)}} is only +available in [=report win=], but not [=report result=]. + Each {{InterestGroupReportingScriptRunnerGlobalScope}} has a
: report url @@ -2601,6 +2634,9 @@ Each {{InterestGroupReportingScriptRunnerGlobalScope}} has a : reporting beacon map :: Null or an [=ordered map=] whose [=map/keys=] are [=strings=] and whose [=map/values=] are [=URLs=]. Defaulting to null. +: reporting macro map +:: Null or an [=ordered map=] whose [=map/keys=] are [=strings=] and whose [=map/values=] are + [=strings=]. Defaulting to null.
@@ -2646,6 +2682,13 @@ Each {{InterestGroupReportingScriptRunnerGlobalScope}} has a reporting beacon map=] to |map|.
+
+ The registerAdMacro(|name|, + |value|) method steps are: + + 1. [=map/Set=] [=this=]'s [=relevant global object=]'s + [=InterestGroupReportingScriptRunnerGlobalScope/reporting macro map=][|name|] to |value|. +
# Interest Group Updates # {#interest-group-updates} @@ -3109,9 +3152,19 @@ An interest group ad is a [=struct=] with the following [=struct/items=]: : metadata :: Null or a [=string=]. Extra arbitary information about this ad, passed to `generateBid()`. : buyer reporting ID -:: Null or a [=string=]. Will be passed in place of interest group name to `reportWin()`, subject to k-anonymity checks. +:: Null or a [=string=]. Will be passed in place of interest group name to [=report win=], subject + to k-anonymity checks. Only meaningful in [=interest group/ads=], but ignored in + [=interest group/ad components=]. : buyer and seller reporting ID -:: Null or a [=string=]. Will be passed in place of interest group name or [=interest group ad/buyer reporting ID=] to `reportWin()` and `reportResult()`, subject to k-anonymity checks. +:: Null or a [=string=]. Will be passed in place of interest group name or + [=interest group ad/buyer reporting ID=] to [=report win=] and [=report result=], subject to + k-anonymity checks. Only meaningful in [=interest group/ads=], but ignored in + [=interest group/ad components=]. +: allowed reporting origins +:: Null or a [=list=] of [=origins=]. A list of up to 10 reporting origins that can receive reports + with registered macros. All origins must be HTTPS origins and + enrolled. Only meaningful in + [=interest group/ads=], but ignored in [=interest group/ad components=]. @@ -3372,6 +3425,8 @@ the seller. :: Null or an {{unsigned short}}. A 0-4095 integer (12-bits) passed to `reportWin()`, with noising. : interest group :: An [=interest group=], whose `generateBid()` invocation generated this bid. +: bid ad +:: The [=interest group ad=] within [=generated bid/interest group=] to display. : modified bid :: Null or a [=bid with currency=]. Being null for top level auction. The bid value a component auction's `scoreAd()` script returns. @@ -3536,6 +3591,11 @@ A reporting result is a [=struct=] with the following [=struct/items= :: Null or an [=ordered map=] whose [=map/keys=] are [=strings=] and whose [=map/values=] are [=URLs=], initially null. Set by {{InterestGroupReportingScriptRunnerGlobalScope/registerAdBeacon(map)}}. + + : reporting macro map + :: Null or an [=ordered map=] whose [=map/keys=] are [=strings=] and whose [=map/values=] are + [=strings=], initially null. Set by + {{InterestGroupReportingScriptRunnerGlobalScope/registerAdMacro(name, value)}}. # Privacy Considerations # {#privacy-considerations}