tor-browser

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

cross-origin.https.window.js (21972B)


      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-4
      8 // META: variant=?5-8
      9 // META: variant=?9-12
     10 // META: variant=?13-last
     11 
     12 "use strict";
     13 
     14 ////////////////////////////////////////////////////////////////////////////////
     15 // Join interest group in iframe tests.
     16 ////////////////////////////////////////////////////////////////////////////////
     17 
     18 subsetTest(promise_test, async test => {
     19  const uuid = generateUuid(test);
     20  let iframe = await createIframe(test, document.location.origin);
     21 
     22  // Join a same-origin InterestGroup in a iframe navigated to its origin.
     23  await runInFrame(test, iframe, `await joinInterestGroup(test_instance, "${uuid}");`);
     24 
     25  // Run an auction using window.location.origin as a bidder. The IG should
     26  // make a bid and win an auction.
     27  await runBasicFledgeTestExpectingWinner(test, uuid);
     28 }, 'Join interest group in same-origin iframe, default permissions.');
     29 
     30 subsetTest(promise_test, async test => {
     31  const uuid = generateUuid(test);
     32  let iframe = await createIframe(test, OTHER_ORIGIN1);
     33 
     34  // Join a cross-origin InterestGroup in a iframe navigated to its origin.
     35  await runInFrame(test, iframe, `await joinInterestGroup(test_instance, "${uuid}");`);
     36 
     37  // Run an auction in this frame using the other origin as a bidder. The IG should
     38  // make a bid and win an auction.
     39  //
     40  // TODO: Once the permission defaults to not being able to join InterestGroups in
     41  // cross-origin iframes, this auction should have no winner.
     42  await runBasicFledgeTestExpectingWinner(
     43      test, uuid,
     44      { interestGroupBuyers: [OTHER_ORIGIN1],
     45        scoreAd: `if (browserSignals.interestGroupOwner !== "${OTHER_ORIGIN1}")
     46                    throw "Wrong owner: " + browserSignals.interestGroupOwner`
     47      });
     48 }, 'Join interest group in cross-origin iframe, default permissions.');
     49 
     50 subsetTest(promise_test, async test => {
     51  const uuid = generateUuid(test);
     52  let iframe = await createIframe(test, OTHER_ORIGIN1, 'join-ad-interest-group');
     53 
     54  // Join a cross-origin InterestGroup in a iframe navigated to its origin.
     55  await runInFrame(test, iframe, `await joinInterestGroup(test_instance, "${uuid}");`);
     56 
     57  // Run an auction in this frame using the other origin as a bidder. The IG should
     58  // make a bid and win an auction.
     59  await runBasicFledgeTestExpectingWinner(
     60      test, uuid,
     61      { interestGroupBuyers: [OTHER_ORIGIN1],
     62        scoreAd: `if (browserSignals.interestGroupOwner !== "${OTHER_ORIGIN1}")
     63                    throw "Wrong owner: " + browserSignals.interestGroupOwner`
     64      });
     65 }, 'Join interest group in cross-origin iframe with join-ad-interest-group permission.');
     66 
     67 subsetTest(promise_test, async test => {
     68  const uuid = generateUuid(test);
     69  let iframe = await createIframe(test, OTHER_ORIGIN1, "join-ad-interest-group 'none'");
     70 
     71  // Try to join an InterestGroup in a cross-origin iframe whose permissions policy
     72  // blocks joining interest groups. An exception should be thrown, and the interest
     73  // group should not be joined.
     74  await runInFrame(test, iframe,
     75                    `try {
     76                       await joinInterestGroup(test_instance, "${uuid}");
     77                     } catch (e) {
     78                       assert_true(e instanceof DOMException, "DOMException thrown");
     79                       assert_equals(e.name, "NotAllowedError", "NotAllowedError DOMException thrown");
     80                       return {result: "success"};
     81                     }
     82                     return "exception unexpectedly not thrown";`);
     83 
     84  // Run an auction in this frame using the other origin as a bidder. Since the join
     85  // should have failed, the auction should have no winner.
     86  await runBasicFledgeTestExpectingNoWinner(
     87      test, uuid,
     88      { interestGroupBuyers: [OTHER_ORIGIN1] });
     89 }, 'Join interest group in cross-origin iframe with join-ad-interest-group permission denied.');
     90 
     91 subsetTest(promise_test, async test => {
     92  const uuid = generateUuid(test);
     93  let iframe = await createIframe(test, OTHER_ORIGIN1, 'join-ad-interest-group');
     94 
     95  // Try to join an IG with the parent's origin as an owner in a cross-origin iframe.
     96  // This should require a .well-known fetch to the parents origin, which will not
     97  // grant permission. The case where permission is granted is not yet testable.
     98  let interestGroup = JSON.stringify(createInterestGroupForOrigin(uuid, window.location.origin));
     99  await runInFrame(test, iframe,
    100                   `try {
    101                      await joinInterestGroup(test_instance, "${uuid}", ${interestGroup});
    102                    } catch (e) {
    103                      assert_true(e instanceof DOMException, "DOMException thrown");
    104                      assert_equals(e.name, "NotAllowedError", "NotAllowedError DOMException thrown");
    105                      return {result: "success"};
    106                    }
    107                    return "exception unexpectedly not thrown";`);
    108 
    109  // Run an auction with this page's origin as a bidder. Since the join
    110  // should have failed, the auction should have no winner.
    111  await runBasicFledgeTestExpectingNoWinner(test, uuid);
    112 }, "Join interest group owned by parent's origin in cross-origin iframe.");
    113 
    114 ////////////////////////////////////////////////////////////////////////////////
    115 // Run auction in iframe tests.
    116 ////////////////////////////////////////////////////////////////////////////////
    117 
    118 subsetTest(promise_test, async test => {
    119  const uuid = generateUuid(test);
    120  await joinInterestGroup(test, uuid);
    121 
    122  let iframe = await createIframe(test, document.location.origin);
    123 
    124  // Join a same-origin InterestGroup in a iframe navigated to its origin.
    125  await runInFrame(test, iframe, `await joinInterestGroup(test_instance, "${uuid}");`);
    126 
    127  // Run auction in same-origin iframe. This should succeed, by default.
    128  await runInFrame(
    129    test, iframe,
    130    `await runBasicFledgeTestExpectingWinner(test_instance, "${uuid}");`);
    131 }, 'Run auction in same-origin iframe, default permissions.');
    132 
    133 subsetTest(promise_test, async test => {
    134  const uuid = generateUuid(test);
    135  // Join an interest group owned by the main frame's origin.
    136  await joinInterestGroup(test, uuid);
    137 
    138  let iframe = await createIframe(test, OTHER_ORIGIN1);
    139 
    140  // Run auction in cross-origin iframe. Currently, this is allowed by default.
    141  await runInFrame(
    142      test, iframe,
    143      `await runBasicFledgeTestExpectingWinner(
    144           test_instance, "${uuid}",
    145           {interestGroupBuyers: ["${window.location.origin}"]});`);
    146 }, 'Run auction in cross-origin iframe, default permissions.');
    147 
    148 subsetTest(promise_test, async test => {
    149  const uuid = generateUuid(test);
    150  // Join an interest group owned by the main frame's origin.
    151  await joinInterestGroup(test, uuid);
    152 
    153  let iframe = await createIframe(test, OTHER_ORIGIN1, "run-ad-auction");
    154 
    155  // Run auction in cross-origin iframe that should allow the auction to occur.
    156  await runInFrame(
    157      test, iframe,
    158      `await runBasicFledgeTestExpectingWinner(
    159           test_instance, "${uuid}",
    160           {interestGroupBuyers: ["${window.location.origin}"]});`);
    161 }, 'Run auction in cross-origin iframe with run-ad-auction permission.');
    162 
    163 subsetTest(promise_test, async test => {
    164  const uuid = generateUuid(test);
    165  // No need to join any interest groups in this case - running an auction
    166  // should only throw an exception based on permissions policy, regardless
    167  // of whether there are any interest groups can participate.
    168 
    169  let iframe = await createIframe(test, OTHER_ORIGIN1, "run-ad-auction 'none'");
    170 
    171  // Run auction in cross-origin iframe that should not allow the auction to occur.
    172  await runInFrame(
    173      test, iframe,
    174      `try {
    175         await runBasicFledgeAuction(test_instance, "${uuid}");
    176       } catch (e) {
    177         assert_true(e instanceof DOMException, "DOMException thrown");
    178         assert_equals(e.name, "NotAllowedError", "NotAllowedError DOMException thrown");
    179         return {result: "success"};
    180       }
    181       throw "Attempting to run auction unexpectedly did not throw"`);
    182 }, 'Run auction in cross-origin iframe with run-ad-auction permission denied.');
    183 
    184 subsetTest(promise_test, async test => {
    185  const uuid = generateUuid(test);
    186  // Join an interest group owned by the main frame's origin.
    187  await joinInterestGroup(test, uuid);
    188 
    189  let iframe = await createIframe(test, OTHER_ORIGIN1, `run-ad-auction ${OTHER_ORIGIN1}`);
    190 
    191  await runInFrame(
    192      test, iframe,
    193      `await runBasicFledgeTestExpectingWinner(
    194        test_instance, "${uuid}",
    195        { interestGroupBuyers: ["${window.location.origin}"],
    196          seller: "${OTHER_ORIGIN2}",
    197          decisionLogicURL: createDecisionScriptURL("${uuid}", {origin: "${OTHER_ORIGIN2}"})
    198        });`);
    199 }, 'Run auction in cross-origin iframe with run-ad-auction for iframe origin, which is different from seller origin.');
    200 
    201 ////////////////////////////////////////////////////////////////////////////////
    202 // Navigate fenced frame iframe tests.
    203 ////////////////////////////////////////////////////////////////////////////////
    204 
    205 subsetTest(promise_test, async test => {
    206  const uuid = generateUuid(test);
    207 
    208  // Join an interest group and run an auction with a winner.
    209  await joinInterestGroup(test, uuid);
    210  let config = await runBasicFledgeTestExpectingWinner(test, uuid);
    211 
    212  // Try to navigate a fenced frame to the winning ad in a cross-origin iframe
    213  // with no fledge-related permissions.
    214  let iframe = await createIframe(
    215      test, OTHER_ORIGIN1, "join-ad-interest-group 'none'; run-ad-auction 'none'");
    216  await runInFrame(
    217      test, iframe,
    218      `await createAndNavigateFencedFrame(test_instance, param);`,
    219      /*param=*/config);
    220  await waitForObservedRequests(
    221      uuid, [createBidderReportURL(uuid), createSellerReportURL(uuid)]);
    222 }, 'Run auction main frame, open winning ad in cross-origin iframe.');
    223 
    224 subsetTest(promise_test, async test => {
    225  const uuid = generateUuid(test);
    226 
    227  let iframe = await createIframe(
    228      test, OTHER_ORIGIN1, "join-ad-interest-group; run-ad-auction");
    229  await runInFrame(
    230      test, iframe,
    231      `await joinInterestGroup(test_instance, "${uuid}");
    232       await runBasicFledgeAuctionAndNavigate(test_instance, "${uuid}");
    233       await waitForObservedRequests(
    234         "${uuid}", [createBidderReportURL("${uuid}"), createSellerReportURL("${uuid}")])`);
    235 }, 'Run auction in cross-origin iframe and open winning ad in nested fenced frame.');
    236 
    237 subsetTest(promise_test, async test => {
    238  const uuid = generateUuid(test);
    239 
    240  // Run an auction in an cross-origin iframe, and get the resulting FencedFrameConfig.
    241  let iframe = await createIframe(
    242      test, OTHER_ORIGIN1, "join-ad-interest-group; run-ad-auction");
    243  let config = await runInFrame(
    244      test, iframe,
    245      `await joinInterestGroup(test_instance, "${uuid}");
    246       let config = await runBasicFledgeTestExpectingWinner(test_instance, "${uuid}");
    247       return {result: "success", returnValue: config};`);
    248  assert_true(config != null, "Value not returned from auction in iframe");
    249  assert_true(config instanceof FencedFrameConfig,
    250    `Wrong value type returned from auction: ${config.constructor.type}`);
    251 
    252  // Loading the winning ad in a fenced frame that's a child of the main frame should
    253  // succeed.
    254  await createAndNavigateFencedFrame(test, config);
    255  await waitForObservedRequests(
    256      uuid,
    257      [ createBidderReportURL(uuid, '1', OTHER_ORIGIN1),
    258        createSellerReportURL(uuid, '1', OTHER_ORIGIN1)]);
    259 }, 'Run auction in cross-origin iframe and open winning ad in a fenced frame child of the main frame.');
    260 
    261 subsetTest(promise_test, async test => {
    262  const uuid = generateUuid(test);
    263 
    264  // Run an auction in an cross-origin iframe, and get the resulting FencedFrameConfig.
    265  let iframe = await createIframe(
    266      test, OTHER_ORIGIN1, "join-ad-interest-group; run-ad-auction");
    267  let config = await runInFrame(
    268      test, iframe,
    269      `await joinInterestGroup(test_instance, "${uuid}");
    270       let config = await runBasicFledgeTestExpectingWinner(test_instance, "${uuid}");
    271       return {result: "success", returnValue: config};`);
    272  assert_true(config != null, "Value not returned from auction in iframe");
    273  assert_true(config instanceof FencedFrameConfig,
    274    `Wrong value type returned from auction: ${config.constructor.type}`);
    275 
    276  // Try to navigate a fenced frame to the winning ad in a cross-origin iframe
    277  // with no fledge-related permissions. The iframe is a different origin from the
    278  // first cross-origin iframe.
    279  let iframe2 = await createIframe(
    280    test, OTHER_ORIGIN2, "join-ad-interest-group 'none'; run-ad-auction 'none'");
    281  await runInFrame(
    282      test, iframe2,
    283      `await createAndNavigateFencedFrame(test_instance, param);`,
    284      /*param=*/config);
    285  await waitForObservedRequests(
    286      uuid,
    287      [ createBidderReportURL(uuid, '1', OTHER_ORIGIN1),
    288        createSellerReportURL(uuid, '1', OTHER_ORIGIN1)]);
    289 }, 'Run auction in cross-origin iframe and open winning ad in a fenced frame child of another cross-origin iframe.');
    290 
    291 ////////////////////////////////////////////////////////////////////////////////
    292 // Other tests.
    293 ////////////////////////////////////////////////////////////////////////////////
    294 
    295 subsetTest(promise_test, async test => {
    296  const uuid = generateUuid(test);
    297 
    298  let iframe = await createIframe(test, OTHER_ORIGIN1, "run-ad-auction");
    299 
    300  // Do everything in a cross-origin iframe, and make sure correct top-frame origin is used.
    301  await runInFrame(
    302      test, iframe,
    303      `const uuid = "${uuid}";
    304       const renderURL = createRenderURL(uuid, /*script=*/null, /*signalsParam=*/'hostname');
    305 
    306       await joinInterestGroup(
    307          test_instance, uuid,
    308          { trustedBiddingSignalsKeys: ['hostname'],
    309            trustedBiddingSignalsURL: TRUSTED_BIDDING_SIGNALS_URL,
    310            ads: [{ renderURL: renderURL }],
    311            biddingLogicURL: createBiddingScriptURL({
    312              generateBid:
    313                  \`if (browserSignals.topWindowHostname !== "${document.location.hostname}")
    314                      throw "Wrong topWindowHostname: " + browserSignals.topWindowHostname;
    315                    if (trustedBiddingSignals.hostname !== '${window.location.hostname}')
    316                      throw 'Wrong hostname: ' + trustedBiddingSignals.hostname;\`})});
    317 
    318       await runBasicFledgeTestExpectingWinner(
    319           test_instance, uuid,
    320           { trustedScoringSignalsURL: TRUSTED_SCORING_SIGNALS_URL,
    321            decisionLogicURL:
    322            createDecisionScriptURL(
    323              uuid,
    324              { scoreAd:
    325                    \`if (browserSignals.topWindowHostname !== "${document.location.hostname}")
    326                        throw "Wrong topWindowHostname: " + browserSignals.topWindowHostname;
    327                      if (trustedScoringSignals.renderURL["\${renderURL}"] !== '${window.location.hostname}')
    328                        throw 'Wrong hostname: ' + trustedScoringSignals.renderURL["\${renderURL}"];\` })});`);
    329 }, 'Different top-frame origin.');
    330 
    331 subsetTest(promise_test, async test => {
    332  const uuid = generateUuid(test);
    333 
    334  let bidderOrigin = OTHER_ORIGIN1;
    335  let sellerOrigin = OTHER_ORIGIN2;
    336  let bidderSendReportToURL = createBidderReportURL(uuid, '1', OTHER_ORIGIN3);
    337  let sellerSendReportToURL = createSellerReportURL(uuid, '2', OTHER_ORIGIN4);
    338  let bidderBeaconURL = createBidderBeaconURL(uuid, '3', OTHER_ORIGIN5);
    339  let sellerBeaconURL = createSellerBeaconURL(uuid, '4', OTHER_ORIGIN6);
    340  let renderURL = createRenderURL(
    341      uuid,
    342      `window.fence.reportEvent({
    343         eventType: "beacon",
    344         eventData: window.location.href,
    345         destination: ["buyer", "seller"]
    346       })`,
    347       /*signalsParams=*/null, OTHER_ORIGIN7);
    348 
    349  let iframe = await createIframe(test, bidderOrigin, "join-ad-interest-group");
    350  let interestGroup = createInterestGroupForOrigin(
    351      uuid, bidderOrigin,
    352      {biddingLogicURL: createBiddingScriptURL(
    353        { origin: bidderOrigin,
    354          generateBid: `if (browserSignals.topWindowHostname !== "${document.location.hostname}")
    355                          throw "Wrong topWindowHostname: " + browserSignals.topWindowHostname;
    356                        if (interestGroup.owner !== "${bidderOrigin}")
    357                          throw "Wrong origin: " + interestGroup.owner;
    358                        if (!interestGroup.biddingLogicURL.startsWith("${bidderOrigin}"))
    359                          throw "Wrong origin: " + interestGroup.biddingLogicURL;
    360                        if (interestGroup.ads[0].renderURL !== "${renderURL}")
    361                          throw "Wrong renderURL: " + interestGroup.ads[0].renderURL;
    362                        if (browserSignals.seller !== "${sellerOrigin}")
    363                          throw "Wrong origin: " + browserSignals.seller;`,
    364          reportWin: `if (browserSignals.topWindowHostname !== "${document.location.hostname}")
    365                        throw "Wrong topWindowHostname: " + browserSignals.topWindowHostname;
    366                      if (browserSignals.seller !== "${sellerOrigin}")
    367                        throw "Wrong seller: " + browserSignals.seller;
    368                      if (browserSignals.interestGroupOwner !== "${bidderOrigin}")
    369                        throw "Wrong interestGroupOwner: " + browserSignals.interestGroupOwner;
    370                      if (browserSignals.renderURL !== "${renderURL}")
    371                        throw "Wrong renderURL: " + browserSignals.renderURL;
    372                      if (browserSignals.seller !== "${sellerOrigin}")
    373                        throw "Wrong seller: " + browserSignals.seller;
    374                      sendReportTo("${bidderSendReportToURL}");
    375                      registerAdBeacon({beacon: "${bidderBeaconURL}"});` }),
    376       ads: [{ renderURL: renderURL }]});
    377  await runInFrame(
    378      test, iframe,
    379      `await joinInterestGroup(test_instance, "${uuid}", ${JSON.stringify(interestGroup)});`);
    380 
    381  await runBasicFledgeAuctionAndNavigate(test, uuid,
    382    { seller: sellerOrigin,
    383      interestGroupBuyers: [bidderOrigin],
    384      decisionLogicURL: createDecisionScriptURL(
    385        uuid,
    386        { origin: sellerOrigin,
    387          scoreAd: `if (browserSignals.topWindowHostname !== "${document.location.hostname}")
    388                      throw "Wrong topWindowHostname: " + browserSignals.topWindowHostname;
    389                    if (auctionConfig.seller !== "${sellerOrigin}")
    390                      throw "Wrong seller: " + auctionConfig.seller;
    391                    if (auctionConfig.interestGroupBuyers[0] !== "${bidderOrigin}")
    392                      throw "Wrong interestGroupBuyers: " + auctionConfig.interestGroupBuyers;
    393                    if (browserSignals.interestGroupOwner !== "${bidderOrigin}")
    394                      throw "Wrong interestGroupOwner: " + browserSignals.interestGroupOwner;
    395                    if (browserSignals.renderURL !== "${renderURL}")
    396                      throw "Wrong renderURL: " + browserSignals.renderURL;`,
    397          reportResult: `if (browserSignals.topWindowHostname !== "${document.location.hostname}")
    398                           throw "Wrong topWindowHostname: " + browserSignals.topWindowHostname;
    399                         if (browserSignals.interestGroupOwner !== "${bidderOrigin}")
    400                           throw "Wrong interestGroupOwner: " + browserSignals.interestGroupOwner;
    401                         if (browserSignals.renderURL !== "${renderURL}")
    402                           throw "Wrong renderURL: " + browserSignals.renderURL;
    403                         sendReportTo("${sellerSendReportToURL}");
    404                         registerAdBeacon({beacon: "${sellerBeaconURL}"});`})
    405     });
    406 
    407  await waitForObservedRequests(
    408      uuid,
    409      [ bidderSendReportToURL,
    410        sellerSendReportToURL,
    411        `${bidderBeaconURL}, body: ${renderURL}`,
    412        `${sellerBeaconURL}, body: ${renderURL}`
    413      ]);
    414 }, 'Single seller auction with as many distinct origins as possible (except no component ads).');
    415 
    416 subsetTest(promise_test, async test => {
    417  const uuid = generateUuid(test);
    418 
    419  // Join an interest group and run an auction with a winner. Use a tracking
    420  // URL for the ad, so that if it's incorrectly loaded in this test, the
    421  // waitForObservedRequests() at the end of the test will see it, and the
    422  // test will fail.
    423  await joinInterestGroup(
    424      test, uuid,
    425      {ads: [{renderURL: createTrackerURL(window.location.origin, uuid, 'track_get', 'renderURL')}]});
    426  let config = await runBasicFledgeTestExpectingWinner(test, uuid);
    427 
    428  // Try to navigate a fenced frame to the winning ad in a new same-origin
    429  // window. This should fail. Unfortunately, there's no assertion that
    430  // can be checked for, and can't communicate with the contents of the
    431  // fenced frame to make sure the load fails.
    432  //
    433  // So instead, join an interest group with a different sendReportTo-url,
    434  // overwriting the previously joined one, and run another auction, loading
    435  // the winner in another fenced frame.
    436  //
    437  // Then wait to see that only the reporting URLs from that second auction
    438  // are requested. They should almost always be requested after the URLs
    439  // from the first auction.
    440  let child_window =
    441      await createFrame(test, document.location.origin, /*is_iframe=*/false);
    442  await runInFrame(
    443      test, child_window,
    444      `await createAndNavigateFencedFrame(test_instance, param);
    445       await joinInterestGroup(
    446          test_instance, "${uuid}",
    447          {biddingLogicURL: createBiddingScriptURL(
    448              {reportWin: "sendReportTo('${createBidderReportURL(uuid, "2")}');" })});
    449       await runBasicFledgeAuctionAndNavigate(test_instance, "${uuid}");`,
    450      /*param=*/config);
    451  await waitForObservedRequests(
    452      uuid, [createBidderReportURL(uuid, "2"), createSellerReportURL(uuid)]);
    453 }, 'Run auction in main frame, try to open winning ad in different same-origin main frame.');