tor-browser

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

tie.https.window.js (5070B)


      1 // META: script=/resources/testdriver.js
      2 // META: script=/resources/testdriver-vendor.js
      3 // META: script=/common/utils.js
      4 // META: script=resources/fledge-util.sub.js
      5 // META: timeout=long
      6 
      7 "use strict";
      8 
      9 // Runs one auction at a time using `auctionConfigOverrides` until the auction
     10 // has a winner.
     11 async function runAuctionsUntilWinner(test, uuid, auctionConfigOverrides) {
     12  let fencedFrameConfig = null;
     13  while (!fencedFrameConfig) {
     14    fencedFrameConfig =
     15        await runBasicFledgeAuction(test, uuid, auctionConfigOverrides);
     16  }
     17  return fencedFrameConfig;
     18 }
     19 
     20 // This tests the case of ties. The winner of an auction is normally checked
     21 // by these tests by checking a report sent when the winner is loaded in a fenced
     22 // frame. Unfortunately, that requires a lot of navigations, which can be slow.
     23 //
     24 // So instead, run a multi-seller auction. The inner auction has two bidders,
     25 // which both bid, and the seller gives them the same score. For the first
     26 // auction, the top-level seller just accepts the only bid it sees, and then
     27 // as usual, we navigate a fenced frame, to learn which bidder won.
     28 //
     29 // The for subsequent auctions, the nested component auction is identical,
     30 // but the top-level auction rejects bids from the bidder that won the
     31 // first auction. So if we have a winner, we know that the other bidder
     32 // won the tie. Auctions are run in parallel until this happens.
     33 //
     34 // The interest groups use "group-by-origin" execution mode, to potentially
     35 // allow the auctions run in parallel to complete faster.
     36 promise_test(async test => {
     37  const uuid = generateUuid(test);
     38 
     39  // Use different report URLs for each interest group, to identify
     40  // which interest group has won an auction.
     41  let reportURLs = [createBidderReportURL(uuid, /*id=*/'1'),
     42                    createBidderReportURL(uuid, /*id=*/'2')];
     43 
     44  // Use different ad URLs for each auction. These need to be distinct
     45  // so that the top-level seller can check the URL to check if the
     46  // winning bid from the component auction has already won an
     47  // auction.
     48  let adURLs = [createRenderURL(uuid),
     49                createRenderURL(uuid, /*script=*/';')];
     50 
     51  await Promise.all(
     52      [ joinInterestGroup(
     53          test, uuid,
     54          { name: 'group 1',
     55            ads: [{ renderURL: adURLs[0] }],
     56            executionMode: 'group-by-origin',
     57            biddingLogicURL: createBiddingScriptURL(
     58                { allowComponentAuction: true,
     59                  reportWin: `sendReportTo("${reportURLs[0]}");`})}),
     60        joinInterestGroup(
     61          test, uuid,
     62          { name: 'group 2',
     63            ads: [{ renderURL: adURLs[1] }],
     64            executionMode: 'group-by-origin',
     65            biddingLogicURL: createBiddingScriptURL(
     66                { allowComponentAuction: true,
     67                  reportWin: `sendReportTo("${reportURLs[1]}");`})})
     68      ]
     69  );
     70 
     71  let componentAuctionConfig = {
     72      seller: window.location.origin,
     73      decisionLogicURL: createDecisionScriptURL(uuid),
     74      interestGroupBuyers: [window.location.origin]
     75  };
     76 
     77  let auctionConfigOverrides = {
     78    decisionLogicURL: createDecisionScriptURL(uuid),
     79    interestGroupBuyers: [],
     80    componentAuctions: [componentAuctionConfig]
     81  };
     82 
     83  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfigOverrides);
     84 
     85  // Waiting for the report URL of the winner should succeed, while waiting for
     86  // the one of the loser should throw. Wait for both, see which succeeds, and
     87  // set "winningAdURL" to the ad URL of the winner.
     88  let winningAdURL = '';
     89  try {
     90    await waitForObservedRequests(uuid, [reportURLs[0]]);
     91    winningAdURL = adURLs[0];
     92  } catch (e) {
     93    await waitForObservedRequests(uuid, [reportURLs[1]]);
     94    winningAdURL = adURLs[1];
     95  }
     96 
     97  // Modify `auctionConfigOverrides` to only accept the ad from the interest
     98  // group that didn't win the first auction.
     99  auctionConfigOverrides.decisionLogicURL =
    100      createDecisionScriptURL(
    101        uuid,
    102        {scoreAd: `if (browserSignals.renderURL === "${winningAdURL}")
    103                     return 0;`});
    104 
    105  // Add an abort controller, so can cancel extra auctions.
    106  let abortController = new AbortController();
    107  auctionConfigOverrides.signal = abortController.signal;
    108 
    109  // Run a bunch of auctions in parallel, until one has a winner.
    110  let fencedFrameConfig = await Promise.any(
    111    [ runAuctionsUntilWinner(test, uuid, auctionConfigOverrides),
    112      runAuctionsUntilWinner(test, uuid, auctionConfigOverrides),
    113      runAuctionsUntilWinner(test, uuid, auctionConfigOverrides),
    114      runAuctionsUntilWinner(test, uuid, auctionConfigOverrides),
    115      runAuctionsUntilWinner(test, uuid, auctionConfigOverrides),
    116      runAuctionsUntilWinner(test, uuid, auctionConfigOverrides)
    117    ]
    118  );
    119  // Abort the other auctions.
    120  abortController.abort('reason');
    121 
    122  // Load the fencedFrameConfig in a fenced frame, and double-check that each
    123  // interest group has won once.
    124  createAndNavigateFencedFrame(test, fencedFrameConfig);
    125  await waitForObservedRequests(uuid, [reportURLs[0], reportURLs[1]]);
    126 }, 'runAdAuction tie.');