tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

component-auction.https.window.js (35094B)


      1 // META: script=/resources/testdriver.js
      2 // META: script=/resources/testdriver-vendor.js
      3 // META: script=/common/utils.js
      4 // META: script=/common/subset-tests.js
      5 // META: script=resources/fledge-util.sub.js
      6 // META: timeout=long
      7 // META: variant=?1-5
      8 // META: variant=?6-10
      9 // META: variant=?11-15
     10 // META: variant=?16-last
     11 
     12 "use strict";
     13 
     14 // Creates an AuctionConfig with a single component auction.
     15 function createComponentAuctionConfig(uuid, auctionConfigOverrides = {},
     16                                      deprecatedRenderURLReplacements = {}) {
     17  let componentAuctionConfig = {
     18    seller: window.location.origin,
     19    decisionLogicURL: createDecisionScriptURL(uuid),
     20    interestGroupBuyers: [window.location.origin],
     21    deprecatedRenderURLReplacements: deprecatedRenderURLReplacements
     22  };
     23 
     24  return {
     25    seller: window.location.origin,
     26    decisionLogicURL: createDecisionScriptURL(uuid),
     27    interestGroupBuyers: [],
     28    componentAuctions: [componentAuctionConfig],
     29    ...auctionConfigOverrides
     30  };
     31 }
     32 
     33 subsetTest(promise_test, async test => {
     34  const uuid = generateUuid(test);
     35 
     36  await joinInterestGroup(
     37      test, uuid,
     38      { biddingLogicURL: createBiddingScriptURL()});
     39 
     40  await runBasicFledgeTestExpectingNoWinner(test, uuid, createComponentAuctionConfig(uuid));
     41 }, 'Component auction allowed not specified by bidder.');
     42 
     43 subsetTest(promise_test, async test => {
     44  const uuid = generateUuid(test);
     45 
     46  await joinInterestGroup(
     47      test, uuid,
     48      { biddingLogicURL: createBiddingScriptURL(
     49        { allowComponentAuction: false })});
     50 
     51  await runBasicFledgeTestExpectingNoWinner(test, uuid, createComponentAuctionConfig(uuid));
     52 }, 'Component auction not allowed by bidder.');
     53 
     54 subsetTest(promise_test, async test => {
     55  const uuid = generateUuid(test);
     56 
     57  await joinInterestGroup(
     58      test, uuid,
     59      { biddingLogicURL: createBiddingScriptURL(
     60        { allowComponentAuction: true })});
     61 
     62  let auctionConfig = createComponentAuctionConfig(uuid);
     63  auctionConfig.componentAuctions[0].decisionLogicURL = createDecisionScriptURL(
     64      uuid,
     65      { scoreAd: "return 5;" });
     66 
     67  await runBasicFledgeTestExpectingNoWinner(test, uuid, auctionConfig);
     68 }, 'Component auction allowed not specified by component seller.');
     69 
     70 subsetTest(promise_test, async test => {
     71  const uuid = generateUuid(test);
     72 
     73  await joinInterestGroup(
     74      test, uuid,
     75      { biddingLogicURL: createBiddingScriptURL(
     76        { allowComponentAuction: true })});
     77 
     78  let auctionConfig = createComponentAuctionConfig(uuid);
     79  auctionConfig.componentAuctions[0].decisionLogicURL = createDecisionScriptURL(
     80      uuid,
     81      { scoreAd: "return {desirability: 5, allowComponentAuction: false};" });
     82 
     83  await runBasicFledgeTestExpectingNoWinner(test, uuid, auctionConfig);
     84 }, 'Component auction not allowed by component seller.');
     85 
     86 subsetTest(promise_test, async test => {
     87  const uuid = generateUuid(test);
     88 
     89  await joinInterestGroup(
     90      test, uuid,
     91      { biddingLogicURL: createBiddingScriptURL(
     92        { allowComponentAuction: true })});
     93 
     94  let auctionConfig = createComponentAuctionConfig(uuid);
     95  auctionConfig.decisionLogicURL = createDecisionScriptURL(
     96      uuid,
     97      { scoreAd: "return 5;" });
     98 
     99  await runBasicFledgeTestExpectingNoWinner(test, uuid, auctionConfig);
    100 }, 'Component auction allowed not specified by top-level seller.');
    101 
    102 subsetTest(promise_test, async test => {
    103  const uuid = generateUuid(test);
    104 
    105  await joinInterestGroup(
    106      test, uuid,
    107      { biddingLogicURL: createBiddingScriptURL(
    108        { allowComponentAuction: true })});
    109 
    110  let auctionConfig = createComponentAuctionConfig(uuid);
    111  auctionConfig.interestGroupBuyers = [window.location.origin];
    112 
    113  try {
    114    await runBasicFledgeAuction(test, uuid, auctionConfig);
    115  } catch (exception) {
    116    assert_true(exception instanceof TypeError, "did not get expected error: " + exception);
    117    return;
    118  }
    119  throw 'Exception unexpectedly not thrown.'
    120 }, 'Component auction top-level auction cannot have buyers.');
    121 
    122 subsetTest(promise_test, async test => {
    123  const uuid = generateUuid(test);
    124 
    125  await joinInterestGroup(
    126      test, uuid,
    127      { biddingLogicURL: createBiddingScriptURL(
    128        { allowComponentAuction: true })});
    129 
    130  let auctionConfig = createComponentAuctionConfig(uuid);
    131  auctionConfig.decisionLogicURL = createDecisionScriptURL(
    132      uuid,
    133      { scoreAd: "return {desirability: 5, allowComponentAuction: false};" });
    134 
    135  await runBasicFledgeTestExpectingNoWinner(test, uuid, auctionConfig);
    136 }, 'Component auction not allowed by top-level seller.');
    137 
    138 subsetTest(promise_test, async test => {
    139  const uuid = generateUuid(test);
    140 
    141  // Use distinct origins so can validate all origin parameters passed to worklets.
    142  let bidder = OTHER_ORIGIN1;
    143  let componentSeller = OTHER_ORIGIN2;
    144  let topLevelSeller = OTHER_ORIGIN3;
    145 
    146  let bidderReportURL = createBidderReportURL(uuid);
    147  let componentSellerReportURL = createSellerReportURL(uuid, /*id=*/"component");
    148  let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/"top");
    149 
    150  // Note that generateBid() and reportWin() receive slightly different
    151  // "browserSignals" fields - only reportWin() gets "interestGroupOwner", so
    152  // need different sets of checks for them.
    153  await joinCrossOriginInterestGroup(
    154      test, uuid, bidder,
    155      { biddingLogicURL: createBiddingScriptURL(
    156        { origin: bidder,
    157          allowComponentAuction: true,
    158          generateBid:
    159            `if (browserSignals.seller !== "${componentSeller}")
    160               throw "Unexpected seller: " + browserSignals.seller;
    161             if (browserSignals.componentSeller !== undefined)
    162               throw "Unexpected componentSeller: " + browserSignals.componentSeller;
    163             if (browserSignals.topLevelSeller !== "${topLevelSeller}")
    164               throw "Unexpected topLevelSeller: " + browserSignals.topLevelSeller;
    165             if (browserSignals.interestGroupOwner !== undefined)
    166               throw "Unexpected interestGroupOwner: " + browserSignals.interestGroupOwner;
    167             if (browserSignals.topWindowHostname !== "${window.location.hostname}")
    168               throw "Unexpected topWindowHostname: " + browserSignals.topWindowHostname;`,
    169          reportWin:
    170            `if (browserSignals.seller !== "${componentSeller}")
    171               throw "Unexpected seller: " + browserSignals.seller;
    172             if (browserSignals.componentSeller !== undefined)
    173               throw "Unexpected componentSeller: " + browserSignals.componentSeller;
    174             if (browserSignals.topLevelSeller !== "${topLevelSeller}")
    175               throw "Unexpected topLevelSeller: " + browserSignals.topLevelSeller;
    176             if (browserSignals.interestGroupOwner !== "${bidder}")
    177               throw "Unexpected interestGroupOwner: " + browserSignals.interestGroupOwner;
    178             if (browserSignals.topWindowHostname !== "${window.location.hostname}")
    179               throw "Unexpected topWindowHostname: " + browserSignals.topWindowHostname;
    180             sendReportTo("${bidderReportURL}");`})});
    181 
    182  // Checks for scoreAd() and reportResult() for the component seller.
    183  let componentSellerChecks =
    184      `if (browserSignals.seller !== undefined)
    185         throw "Unexpected seller: " + browserSignals.seller;
    186       if (browserSignals.componentSeller !== undefined)
    187         throw "Unexpected componentSeller: " + browserSignals.componentSeller;
    188       if (browserSignals.topLevelSeller !== "${topLevelSeller}")
    189         throw "Unexpected topLevelSeller: " + browserSignals.topLevelSeller;
    190       if (browserSignals.interestGroupOwner !== "${bidder}")
    191         throw "Unexpected interestGroupOwner: " + browserSignals.interestGroupOwner;
    192       if (browserSignals.topWindowHostname !== "${window.location.hostname}")
    193         throw "Unexpected topWindowHostname: " + browserSignals.topWindowHostname;`;
    194 
    195  let componentAuctionConfig = {
    196    seller: componentSeller,
    197    decisionLogicURL: createDecisionScriptURL(
    198        uuid,
    199        { origin: componentSeller,
    200          scoreAd: componentSellerChecks,
    201          reportResult: `${componentSellerChecks}
    202                          sendReportTo("${componentSellerReportURL}");` }),
    203    interestGroupBuyers: [bidder]
    204  };
    205 
    206  // Checks for scoreAd() and reportResult() for the top-level seller.
    207  let topLevelSellerChecks =
    208      `if (browserSignals.seller !== undefined)
    209         throw "Unexpected seller: " + browserSignals.seller;
    210       if (browserSignals.componentSeller !== "${componentSeller}")
    211         throw "Unexpected componentSeller: " + browserSignals.componentSeller;
    212       if (browserSignals.topLevelSeller !== undefined)
    213         throw "Unexpected topLevelSeller: " + browserSignals.topLevelSeller;
    214       if (browserSignals.interestGroupOwner !== "${bidder}")
    215         throw "Unexpected interestGroupOwner: " + browserSignals.interestGroupOwner;
    216       if (browserSignals.topWindowHostname !== "${window.location.hostname}")
    217         throw "Unexpected topWindowHostname: " + browserSignals.topWindowHostname;`;
    218 
    219  let auctionConfigOverrides = {
    220    seller: topLevelSeller,
    221    decisionLogicURL: createDecisionScriptURL(
    222        uuid,
    223        { origin: topLevelSeller,
    224          scoreAd: topLevelSellerChecks,
    225          reportResult: `${topLevelSellerChecks}
    226                         sendReportTo("${topLevelSellerReportURL}");` }),
    227    interestGroupBuyers: [],
    228    componentAuctions: [componentAuctionConfig]
    229  };
    230 
    231  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfigOverrides);
    232  await waitForObservedRequests(
    233      uuid,
    234      [bidderReportURL, componentSellerReportURL, topLevelSellerReportURL]);
    235 }, 'Component auction browserSignals origins.');
    236 
    237 subsetTest(promise_test, async test => {
    238  const uuid = generateUuid(test);
    239 
    240  let bidderReportURL = createBidderReportURL(uuid);
    241  let componentSellerReportURL = createSellerReportURL(uuid, /*id=*/"component");
    242  let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/"top");
    243 
    244  await joinInterestGroup(
    245      test, uuid,
    246      { biddingLogicURL: createBiddingScriptURL(
    247        { allowComponentAuction: true,
    248          bid: 5,
    249          reportWin:
    250            `if (browserSignals.bid !== 5)
    251               throw "Unexpected bid: " + browserSignals.bid;
    252             sendReportTo("${bidderReportURL}");`})});
    253 
    254  let auctionConfig = createComponentAuctionConfig(uuid);
    255 
    256  auctionConfig.componentAuctions[0].decisionLogicURL =
    257    createDecisionScriptURL(
    258        uuid,
    259        { scoreAd:
    260              `if (bid !== 5)
    261                 throw "Unexpected component bid: " + bid`,
    262          reportResult:
    263              `if (browserSignals.bid !== 5)
    264                 throw "Unexpected component bid: " + browserSignals.bid;
    265               if (browserSignals.modifiedBid !== undefined)
    266                 throw "Unexpected component modifiedBid: " + browserSignals.modifiedBid;
    267               sendReportTo("${componentSellerReportURL}");` });
    268 
    269  auctionConfig.decisionLogicURL =
    270    createDecisionScriptURL(
    271        uuid,
    272        { scoreAd:
    273              `if (bid !== 5)
    274                 throw "Unexpected top-level bid: " + bid`,
    275          reportResult:
    276              `if (browserSignals.bid !== 5)
    277                 throw "Unexpected top-level bid: " + browserSignals.bid;
    278               if (browserSignals.modifiedBid !== undefined)
    279                 throw "Unexpected top-level modifiedBid: " + browserSignals.modifiedBid;
    280               sendReportTo("${topLevelSellerReportURL}");` });
    281 
    282  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
    283  await waitForObservedRequests(
    284      uuid,
    285      [bidderReportURL, componentSellerReportURL, topLevelSellerReportURL]);
    286 }, 'Component auction unmodified bid.');
    287 
    288 subsetTest(promise_test, async test => {
    289  const uuid = generateUuid(test);
    290 
    291  let bidderReportURL = createBidderReportURL(uuid);
    292  let componentSellerReportURL = createSellerReportURL(uuid, /*id=*/"component");
    293  let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/"top");
    294 
    295  await joinInterestGroup(
    296      test, uuid,
    297      { biddingLogicURL: createBiddingScriptURL(
    298        { allowComponentAuction: true,
    299          bid: 5,
    300          reportWin:
    301            `if (browserSignals.bid !== 5)
    302               throw "Unexpected bid: " + browserSignals.bid;
    303             sendReportTo("${bidderReportURL}");`})});
    304 
    305  let auctionConfig = createComponentAuctionConfig(uuid);
    306 
    307  auctionConfig.componentAuctions[0].decisionLogicURL =
    308      createDecisionScriptURL(
    309          uuid,
    310          { scoreAd:
    311                `if (bid !== 5)
    312                   throw "Unexpected component bid: " + bid
    313                 return {desirability: 5, allowComponentAuction: true, bid: 4};`,
    314            reportResult:
    315                `if (browserSignals.bid !== 5)
    316                   throw "Unexpected component bid: " + browserSignals.bid;
    317                 if (browserSignals.modifiedBid !== 4)
    318                   throw "Unexpected component modifiedBid: " + browserSignals.modifiedBid;
    319                 sendReportTo("${componentSellerReportURL}");` });
    320 
    321  auctionConfig.decisionLogicURL =
    322      createDecisionScriptURL(
    323          uuid,
    324          { scoreAd:
    325                `if (bid !== 4)
    326                   throw "Unexpected top-level bid: " + bid`,
    327            reportResult:
    328                `if (browserSignals.bid !== 4)
    329                   throw "Unexpected top-level bid: " + browserSignals.bid;
    330                 if (browserSignals.modifiedBid !== undefined)
    331                   throw "Unexpected top-level modifiedBid: " + browserSignals.modifiedBid;
    332                 sendReportTo("${topLevelSellerReportURL}");` });
    333 
    334  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
    335  await waitForObservedRequests(
    336      uuid,
    337      [bidderReportURL, componentSellerReportURL, topLevelSellerReportURL]);
    338 }, 'Component auction modified bid.');
    339 
    340 subsetTest(promise_test, async test => {
    341  const uuid = generateUuid(test);
    342 
    343  let bidderReportURL = createBidderReportURL(uuid);
    344  let componentSellerReportURL = createSellerReportURL(uuid, /*id=*/"component");
    345  let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/"top");
    346 
    347  await joinInterestGroup(
    348      test, uuid,
    349      { biddingLogicURL: createBiddingScriptURL(
    350        { allowComponentAuction: true,
    351          bid: 5,
    352          reportWin:
    353            `if (browserSignals.bid !== 5)
    354               throw "Unexpected bid: " + browserSignals.bid;
    355             sendReportTo("${bidderReportURL}");`})});
    356 
    357  let auctionConfig = createComponentAuctionConfig(uuid);
    358 
    359  auctionConfig.componentAuctions[0].decisionLogicURL =
    360      createDecisionScriptURL(
    361          uuid,
    362          { scoreAd:
    363                `if (bid !== 5)
    364                   throw "Unexpected component bid: " + bid
    365                 return {desirability: 5, allowComponentAuction: true, bid: 5};`,
    366            reportResult:
    367                `if (browserSignals.bid !== 5)
    368                   throw "Unexpected component bid: " + browserSignals.bid;
    369                 if (browserSignals.modifiedBid !== 5)
    370                   throw "Unexpected component modifiedBid: " + browserSignals.modifiedBid;
    371                 sendReportTo("${componentSellerReportURL}");` });
    372 
    373  auctionConfig.decisionLogicURL =
    374      createDecisionScriptURL(
    375          uuid,
    376          { scoreAd:
    377                `if (bid !== 5)
    378                   throw "Unexpected top-level bid: " + bid`,
    379            reportResult:
    380                `if (browserSignals.bid !== 5)
    381                   throw "Unexpected top-level bid: " + browserSignals.bid;
    382                 if (browserSignals.modifiedBid !== undefined)
    383                   throw "Unexpected top-level modifiedBid: " + browserSignals.modifiedBid;
    384                 sendReportTo("${topLevelSellerReportURL}");` });
    385 
    386  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
    387  await waitForObservedRequests(
    388      uuid,
    389      [bidderReportURL, componentSellerReportURL, topLevelSellerReportURL]);
    390 }, 'Component auction modified bid to same value.');
    391 
    392 subsetTest(promise_test, async test => {
    393  const uuid = generateUuid(test);
    394 
    395  let bidderReportURL = createBidderReportURL(uuid);
    396  let componentSellerReportURL = createSellerReportURL(uuid, /*id=*/"component");
    397  let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/"top");
    398 
    399  await joinInterestGroup(
    400      test, uuid,
    401      { biddingLogicURL: createBiddingScriptURL(
    402        { allowComponentAuction: true,
    403          bid: 5,
    404          reportWin:
    405            `if (browserSignals.bid !== 5)
    406               throw "Unexpected bid: " + browserSignals.bid;
    407             sendReportTo("${bidderReportURL}");`})});
    408 
    409  let auctionConfig = createComponentAuctionConfig(uuid);
    410 
    411  auctionConfig.componentAuctions[0].decisionLogicURL =
    412      createDecisionScriptURL(
    413          uuid,
    414          { scoreAd:
    415                `if (bid !== 5)
    416                   throw "Unexpected component bid: " + bid`,
    417            reportResult:
    418                `if (browserSignals.bid !== 5)
    419                   throw "Unexpected component bid: " + browserSignals.bid;
    420                 if (browserSignals.modifiedBid !== undefined)
    421                   throw "Unexpected component modifiedBid: " + browserSignals.modifiedBid;
    422                 sendReportTo("${componentSellerReportURL}");` });
    423 
    424  auctionConfig.decisionLogicURL =
    425      createDecisionScriptURL(
    426          uuid,
    427          { scoreAd:
    428                `if (bid !== 5)
    429                   throw "Unexpected top-level bid: " + bid
    430                 return {desirability: 5, allowComponentAuction: true, bid: 4};`,
    431            reportResult:
    432                `if (browserSignals.bid !== 5)
    433                   throw "Unexpected top-level bid: " + browserSignals.bid;
    434                 if (browserSignals.modifiedBid !== undefined)
    435                   throw "Unexpected top-level modifiedBid: " + browserSignals.modifiedBid;
    436                 sendReportTo("${topLevelSellerReportURL}");` });
    437 
    438  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
    439  await waitForObservedRequests(
    440      uuid,
    441      [bidderReportURL, componentSellerReportURL, topLevelSellerReportURL]);
    442 }, 'Top-level auction cannot modify bid.');
    443 
    444 subsetTest(promise_test, async test => {
    445  const uuid = generateUuid(test);
    446 
    447  let bidderReportURL = createBidderReportURL(uuid);
    448  let componentSellerReportURL = createSellerReportURL(uuid, /*id=*/"component");
    449  let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/"top");
    450 
    451  await joinInterestGroup(
    452      test, uuid,
    453      { biddingLogicURL: createBiddingScriptURL(
    454        { allowComponentAuction: true,
    455          reportWin:
    456            `if (browserSignals.desirability !== undefined)
    457               throw "Unexpected desirability: " + browserSignals.desirability;
    458             sendReportTo("${bidderReportURL}");`})});
    459 
    460  let auctionConfig = createComponentAuctionConfig(uuid);
    461 
    462  auctionConfig.componentAuctions[0].decisionLogicURL =
    463      createDecisionScriptURL(
    464          uuid,
    465          { scoreAd:
    466                `return {desirability: 3, allowComponentAuction: true};`,
    467            reportResult:
    468                `if (browserSignals.desirability !== 3)
    469                  throw "Unexpected component desirability: " + browserSignals.desirability;
    470                 sendReportTo("${componentSellerReportURL}");` });
    471 
    472  auctionConfig.decisionLogicURL =
    473      createDecisionScriptURL(
    474          uuid,
    475          { scoreAd:
    476                `return {desirability: 4, allowComponentAuction: true};`,
    477            reportResult:
    478                `if (browserSignals.desirability !== 4)
    479                  throw "Unexpected component desirability: " + browserSignals.desirability;
    480                 sendReportTo("${topLevelSellerReportURL}");` });
    481 
    482  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
    483  await waitForObservedRequests(
    484      uuid,
    485      [bidderReportURL, componentSellerReportURL, topLevelSellerReportURL]);
    486 }, 'Component auction desirability.');
    487 
    488 subsetTest(promise_test, async test => {
    489  const uuid = generateUuid(test);
    490 
    491  // An auction with two components, each of which has a distinct bidder origin,
    492  // so the bidder in the second component is OTHER_ORIGIN1). The bidder in the
    493  // first component auction bids more and is given the highest of all
    494  // desirability scores in the auction by its component seller, but the
    495  // top-level seller prefers bidder 2.
    496  let bidder1ReportURL = createBidderReportURL(uuid, /*id=*/1);
    497  let bidder2ReportURL = createBidderReportURL(uuid, /*id=*/2);
    498  let componentSeller1ReportURL = createSellerReportURL(uuid, /*id=*/"component1");
    499  let componentSeller2ReportURL = createSellerReportURL(uuid, /*id=*/"component2");
    500  let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/"top");
    501 
    502  await Promise.all([
    503      joinInterestGroup(
    504          test, uuid,
    505          { biddingLogicURL: createBiddingScriptURL(
    506            { bid: 10,
    507              allowComponentAuction: true,
    508              reportWin:
    509                `sendReportTo("${bidder1ReportURL}");`})}),
    510      joinCrossOriginInterestGroup(test, uuid, OTHER_ORIGIN1,
    511        { biddingLogicURL: createBiddingScriptURL(
    512          { origin: OTHER_ORIGIN1,
    513            bid: 2,
    514            allowComponentAuction: true,
    515            reportWin:
    516              `if (browserSignals.bid !== 2)
    517                 throw "Unexpected bid: " + browserSignals.bid;
    518               sendReportTo("${bidder2ReportURL}");`})})
    519  ]);
    520 
    521  let auctionConfig = createComponentAuctionConfig(uuid);
    522 
    523  auctionConfig.componentAuctions[0].decisionLogicURL =
    524      createDecisionScriptURL(
    525          uuid,
    526          { scoreAd:
    527                `return {desirability: 10, allowComponentAuction: true};`,
    528            reportResult:
    529                `sendReportTo("${componentSeller1ReportURL}");` });
    530 
    531  auctionConfig.componentAuctions[1] = {
    532    ...auctionConfig.componentAuctions[0],
    533    interestGroupBuyers: [OTHER_ORIGIN1],
    534    decisionLogicURL: createDecisionScriptURL(
    535        uuid,
    536        { scoreAd:
    537              `return {desirability: 1, allowComponentAuction: true};`,
    538          reportResult:
    539              `if (browserSignals.desirability !== 1)
    540                 throw "Unexpected component desirability: " + browserSignals.desirability;
    541               sendReportTo("${componentSeller2ReportURL}");` })
    542  }
    543 
    544  auctionConfig.decisionLogicURL =
    545      createDecisionScriptURL(
    546          uuid,
    547          { scoreAd:
    548                `return {desirability: 11 - bid, allowComponentAuction: true};`,
    549            reportResult:
    550                `if (browserSignals.desirability !== 9)
    551                   throw "Unexpected component desirability: " + browserSignals.desirability;
    552                 sendReportTo("${topLevelSellerReportURL}");` });
    553 
    554  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
    555  await waitForObservedRequests(
    556      uuid,
    557      [bidder2ReportURL, componentSeller2ReportURL, topLevelSellerReportURL]);
    558 }, 'Component auction desirability two sellers, two bidders.');
    559 
    560 subsetTest(promise_test, async test => {
    561  const uuid = generateUuid(test);
    562 
    563  let renderURL1 = createRenderURL(uuid);
    564  let renderURL2 = createRenderURL(uuid, /*script=*/';');
    565 
    566  // The same bidder uses different ads, bids, and reporting URLs for different
    567  // component sellers.
    568  let bidderReportURL1 = createBidderReportURL(uuid, /*id=*/1);
    569  let bidderReportURL2 = createBidderReportURL(uuid, /*id=*/2);
    570  let componentSeller1ReportURL = createSellerReportURL(uuid, /*id=*/"component1");
    571  let componentSeller2ReportURL = createSellerReportURL(uuid, /*id=*/"component2");
    572  let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/"top");
    573 
    574  await joinInterestGroup(
    575        test, uuid,
    576        { ads: [{ renderURL: renderURL1 }, { renderURL: renderURL2 }],
    577          biddingLogicURL: createBiddingScriptURL(
    578          { allowComponentAuction: true,
    579            generateBid:
    580              // "auctionSignals" contains the bid and the report URL, to
    581              // make the same bidder behave differently in the two
    582              // auctions.
    583              'return auctionSignals;',
    584            reportWin:
    585              `if (browserSignals.renderURL !== "${renderURL2}")
    586                 throw "Wrong winner: " + browserSignals.renderURL;
    587               sendReportTo(auctionSignals.reportURL);`})});
    588 
    589  let auctionConfig = createComponentAuctionConfig(uuid);
    590 
    591  auctionConfig.componentAuctions[0].decisionLogicURL =
    592      createDecisionScriptURL(
    593          uuid,
    594          { scoreAd:
    595                `return {desirability: 10, allowComponentAuction: true};`,
    596            reportResult:
    597                `sendReportTo("${componentSeller1ReportURL}");` });
    598  // "auctionSignals" contains the bid and the report URL, to
    599  // make the same bidder behave differently in the two
    600  // auctions.
    601  auctionConfig.componentAuctions[0].auctionSignals = {
    602    bid: 10,
    603    allowComponentAuction: true,
    604    render: renderURL1,
    605    reportURL: bidderReportURL1
    606  };
    607 
    608  auctionConfig.componentAuctions[1] = {
    609    ...auctionConfig.componentAuctions[0],
    610    auctionSignals: {
    611      bid: 2,
    612      allowComponentAuction: true,
    613      render: renderURL2,
    614      reportURL: bidderReportURL2
    615    },
    616    decisionLogicURL: createDecisionScriptURL(
    617        uuid,
    618        { scoreAd:
    619              `return {desirability: 1, allowComponentAuction: true};`,
    620          reportResult:
    621              `if (browserSignals.desirability !== 1)
    622                 throw "Unexpected component desirability: " + browserSignals.desirability;
    623               if (browserSignals.renderURL !== "${renderURL2}")
    624                 throw "Wrong winner: " + browserSignals.renderURL;
    625               sendReportTo("${componentSeller2ReportURL}");` })
    626  }
    627 
    628  auctionConfig.decisionLogicURL =
    629      createDecisionScriptURL(
    630          uuid,
    631          { scoreAd:
    632                `return {desirability: 11 - bid, allowComponentAuction: true};`,
    633            reportResult:
    634                `if (browserSignals.desirability !== 9)
    635                   throw "Unexpected component desirability: " + browserSignals.desirability;
    636                 if (browserSignals.renderURL !== "${renderURL2}")
    637                   throw "Wrong winner: " + browserSignals.renderURL;
    638                 sendReportTo("${topLevelSellerReportURL}");` });
    639 
    640  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
    641  await waitForObservedRequests(
    642      uuid,
    643      [bidderReportURL2, componentSeller2ReportURL, topLevelSellerReportURL]);
    644 }, 'Component auction desirability and renderURL two sellers, one bidder.');
    645 
    646 subsetTest(promise_test, async test => {
    647  const uuid = generateUuid(test);
    648 
    649  // The renderURLs / report URLs for the first/second iterations of the auction.
    650  let renderURL1 = createRenderURL(uuid);
    651  let renderURL2 = createRenderURL(uuid, /*script=*/';');
    652  let bidderReportURL1 = createBidderReportURL(uuid, /*id=*/1);
    653  let bidderReportURL2 = createBidderReportURL(uuid, /*id=*/2);
    654  let seller1ReportURL = createSellerReportURL(uuid, /*id=*/1);
    655  let seller2ReportURL = createSellerReportURL(uuid, /*id=*/2);
    656 
    657  await joinInterestGroup(
    658        test, uuid,
    659        { ads: [{ renderURL: renderURL1 }, { renderURL: renderURL2 }],
    660          biddingLogicURL: createBiddingScriptURL(
    661          { allowComponentAuction: true,
    662            generateBid:
    663              `// If this is the first recorded win, use "renderURL1"
    664               if (browserSignals.bidCount === 0 &&
    665                   browserSignals.prevWinsMs.length === 0) {
    666                 return {bid: 2, allowComponentAuction: true, render: "${renderURL1}"};
    667               }
    668 
    669               // Otherwise, check that a single bid and win were reported, despite the
    670               // bidder bidding twice in the first auction, once for each component
    671               // auction.
    672               if (browserSignals.bidCount === 1 &&
    673                   browserSignals.prevWinsMs.length === 1 &&
    674                   typeof browserSignals.prevWinsMs[0][0] === "number" &&
    675                   browserSignals.prevWinsMs[0][1].renderURL === "${renderURL1}") {
    676                 return {bid: 1, allowComponentAuction: true, render: "${renderURL2}"};
    677               }
    678               throw "Unexpected browserSignals: " + JSON.stringify(browserSignals);`,
    679            reportWin:
    680              `if (browserSignals.renderURL === "${renderURL1}")
    681                 sendReportTo("${bidderReportURL1}");
    682               if (browserSignals.renderURL === "${renderURL2}")
    683                 sendReportTo("${bidderReportURL2}");`})});
    684 
    685  // Auction has two component auctions with different sellers but the same
    686  // single bidder. The first component auction only accepts bids with
    687  // "renderURL1", the second only accepts bids with "renderURL2".
    688  let auctionConfig = createComponentAuctionConfig(uuid);
    689  auctionConfig.componentAuctions[0].decisionLogicURL =
    690      createDecisionScriptURL(
    691          uuid,
    692          { scoreAd: `if (browserSignals.renderURL !== '${renderURL1}')
    693                        throw 'Wrong ad';`,
    694            reportResult: `sendReportTo('${seller1ReportURL}');`}
    695      );
    696 
    697  auctionConfig.componentAuctions[1] = {
    698      seller: OTHER_ORIGIN1,
    699      interestGroupBuyers: [window.location.origin],
    700      decisionLogicURL: createDecisionScriptURL(
    701          uuid,
    702          { origin: OTHER_ORIGIN1,
    703            scoreAd: `if (browserSignals.renderURL !== '${renderURL2}')
    704                        throw 'Wrong ad';`,
    705            reportResult: `sendReportTo('${seller2ReportURL}');`}
    706      )
    707  };
    708 
    709  // In the first auction, the bidder should use "renderURL1", which the first
    710  // component auction allows. `prevWinsMs` and `numBids` should be updated.
    711  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
    712  await waitForObservedRequests(
    713      uuid,
    714      [bidderReportURL1, seller1ReportURL]);
    715 
    716  // In the second auction, the bidder should use "renderURL2", which the second
    717  // component auction allows. `prevWinsMs` and `numBids` should reflect the updated
    718  // value.
    719  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
    720  await waitForObservedRequests(
    721      uuid,
    722      [bidderReportURL1, seller1ReportURL, bidderReportURL2, seller2ReportURL]);
    723 }, `Component auction prevWinsMs and numBids updating in one component seller's auction, read in another's.`);
    724 
    725 
    726 const makeDeprecatedRenderURLReplacementTest = ({
    727  name,
    728  deprecatedRenderURLReplacements,
    729 }) => {
    730  subsetTest(promise_test, async test => {
    731    const uuid = generateUuid(test);
    732 
    733    let bidderReportURL = createBidderReportURL(uuid);
    734    let componentSellerReportURL = createSellerReportURL(uuid, /*id=*/"component");
    735    let topLevelSellerReportURL = createSellerReportURL(uuid, /*id=*/"top");
    736 
    737    // These are used within the URLs for deprecatedRenderURLReplacement tests.
    738    const renderURLReplacementsStrings = createStringBeforeAndAfterReplacements(deprecatedRenderURLReplacements);
    739    const beforeReplacementsString = renderURLReplacementsStrings.beforeReplacements;
    740    const afterReplacementsString = renderURLReplacementsStrings.afterReplacements;
    741    const renderURLBeforeReplacements = createTrackerURL(window.location.origin, uuid, 'track_get', beforeReplacementsString);
    742    const renderURLAfterReplacements = createTrackerURL(window.location.origin, uuid, 'track_get', afterReplacementsString);
    743 
    744    await joinInterestGroup(
    745      test, uuid,
    746      {
    747        ads: [{ renderURL: renderURLBeforeReplacements }],
    748        biddingLogicURL: createBiddingScriptURL(
    749          {
    750            allowComponentAuction: true,
    751            bid: 5,
    752            reportWin:
    753              `if (browserSignals.bid !== 5)
    754                 throw "Unexpected bid: " + browserSignals.bid;
    755               sendReportTo("${bidderReportURL}");`
    756          })
    757      });
    758 
    759    let auctionConfig = createComponentAuctionConfig(uuid, {}, deprecatedRenderURLReplacements);
    760 
    761    auctionConfig.componentAuctions[0].decisionLogicURL =
    762      createDecisionScriptURL(
    763        uuid,
    764        {
    765          scoreAd:
    766            `if (bid !== 5)
    767                   throw "Unexpected component bid: " + bid`,
    768          reportResult:
    769            `if (browserSignals.bid !== 5)
    770                   throw "Unexpected component bid: " + browserSignals.bid;
    771                 if (browserSignals.modifiedBid !== undefined)
    772                   throw "Unexpected component modifiedBid: " + browserSignals.modifiedBid;
    773                 sendReportTo("${componentSellerReportURL}");`
    774        });
    775 
    776    auctionConfig.decisionLogicURL =
    777      createDecisionScriptURL(
    778        uuid,
    779        {
    780          scoreAd:
    781            `if (bid !== 5)
    782                   throw "Unexpected top-level bid: " + bid`,
    783          reportResult:
    784            `if (browserSignals.bid !== 5)
    785                   throw "Unexpected top-level bid: " + browserSignals.bid;
    786                 if (browserSignals.modifiedBid !== undefined)
    787                   throw "Unexpected top-level modifiedBid: " + browserSignals.modifiedBid;
    788                 sendReportTo("${topLevelSellerReportURL}");`
    789        });
    790 
    791    await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfig);
    792    await waitForObservedRequests(
    793      uuid,
    794      [bidderReportURL, componentSellerReportURL, topLevelSellerReportURL, renderURLAfterReplacements]);
    795  }, name);
    796 };
    797 
    798 makeDeprecatedRenderURLReplacementTest({
    799  name: 'Replacements with brackets.',
    800  deprecatedRenderURLReplacements: { '${EXAMPLE-MACRO}': 'SSP' }
    801 });
    802 
    803 makeDeprecatedRenderURLReplacementTest({
    804  name: 'Replacements with percents.',
    805  deprecatedRenderURLReplacements: { '%%EXAMPLE-MACRO%%': 'SSP' }
    806 });
    807 
    808 makeDeprecatedRenderURLReplacementTest({
    809  name: 'Replacements with multiple replacements.',
    810  deprecatedRenderURLReplacements: { '${EXAMPLE-MACRO1}': 'SSP1', '%%EXAMPLE-MACRO2%%': 'SSP2' }
    811 });
    812 
    813 subsetTest(promise_test, async test => {
    814  const uuid = generateUuid(test);
    815  let deprecatedRenderURLReplacements = { '${EXAMPLE-MACRO1}': 'SSP1', '%%EXAMPLE-MACRO2%%': 'SSP2' };
    816  const renderURLReplacementsStrings = createStringBeforeAndAfterReplacements(deprecatedRenderURLReplacements);
    817  let beforeReplacementsString = renderURLReplacementsStrings.beforeReplacements;
    818 
    819  await joinInterestGroup(
    820    test, uuid,
    821    {
    822      ads: [{ renderURL: createTrackerURL(window.location.origin, uuid, 'track_get', beforeReplacementsString) }],
    823      biddingLogicURL: createBiddingScriptURL({allowComponentAuction: true})
    824    });
    825  let auctionConfigOverride = {deprecatedRenderURLReplacements: deprecatedRenderURLReplacements }
    826  let auctionConfig = createComponentAuctionConfig(uuid,/*auctionConfigOverride=*/auctionConfigOverride,
    827  /*deprecatedRenderURLReplacements=*/deprecatedRenderURLReplacements);
    828 
    829  auctionConfig.componentAuctions[0].decisionLogicURL = createDecisionScriptURL(uuid);
    830 
    831    try {
    832      await runBasicFledgeAuction(test, uuid, auctionConfig);
    833    } catch (exception) {
    834      assert_true(exception instanceof TypeError, "did not get expected error: " + exception);
    835      return;
    836    }
    837    throw 'Exception unexpectedly not thrown.'
    838 }, "deprecatedRenderURLReplacements cause error if passed in top level auction and component auction.");