tor-browser

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

clear-origin-joined-ad-interest-groups.https.window.js (14218B)


      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: script=/common/subset-tests.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 // Basic tests with no interest groups joined.
     16 ///////////////////////////////////////////////////////////////////////////////
     17 
     18 subsetTest(promise_test, async test => {
     19  await navigator.clearOriginJoinedAdInterestGroups(window.location.origin);
     20 }, 'clearOriginJoinedAdInterestGroups(), no groups joined, no group list.');
     21 
     22 subsetTest(promise_test, async test => {
     23  await navigator.clearOriginJoinedAdInterestGroups(window.location.origin, []);
     24 }, 'clearOriginJoinedAdInterestGroups(), no groups joined, group list.');
     25 
     26 subsetTest(promise_test, async test => {
     27  try {
     28    await navigator.clearOriginJoinedAdInterestGroups(OTHER_ORIGIN1);
     29    throw 'Exception unexpectedly not thrown';
     30  } catch (e) {
     31    if (!(e instanceof DOMException) || e.name !== 'NotAllowedError') {
     32      throw 'Wrong exception thrown: ' + e.toString();
     33    }
     34  }
     35 }, 'clearOriginJoinedAdInterestGroups(), cross-origin, no groups joined, no group list.');
     36 
     37 subsetTest(promise_test, async test => {
     38  try {
     39    await navigator.clearOriginJoinedAdInterestGroups(OTHER_ORIGIN1, []);
     40    throw 'Exception unexpectedly not thrown';
     41  } catch (e) {
     42    if (!(e instanceof DOMException) || e.name !== 'NotAllowedError') {
     43      throw 'Wrong exception thrown: ' + e.toString();
     44    }
     45  }
     46 }, 'clearOriginJoinedAdInterestGroups(), cross-origin, no groups joined, group list.');
     47 
     48 ///////////////////////////////////////////////////////////////////////////////
     49 // Tests where interest groups are all owned by document.location.origin.
     50 ///////////////////////////////////////////////////////////////////////////////
     51 
     52 subsetTest(promise_test, async test => {
     53  const uuid = generateUuid(test);
     54 
     55  // Join 3 groups.
     56  await joinInterestGroup(test, uuid);
     57  await joinInterestGroup(test, uuid, {name: 'group 2'});
     58  await joinInterestGroup(test, uuid, {name: 'group 3'});
     59 
     60  // A single clear should leave them all.
     61  await navigator.clearOriginJoinedAdInterestGroups(window.location.origin);
     62 
     63  // Confirm that they were left.
     64  await runBasicFledgeTestExpectingNoWinner(test, uuid);
     65 }, 'clearOriginJoinedAdInterestGroups(), multiple groups joined, no group list.');
     66 
     67 subsetTest(promise_test, async test => {
     68  const uuid = generateUuid(test);
     69 
     70  let group1ReportURL = createBidderReportURL(uuid, /*id=*/'1');
     71  let group2ReportURL = createBidderReportURL(uuid, /*id=*/'2');
     72  let group3ReportURL = createBidderReportURL(uuid, /*id=*/'3');
     73 
     74  // Join 3 groups, with distinct report URLs and increasing bid amounts.
     75  // Set "executionMode" to "group-by-origin" for two of them, since cross-origin
     76  // leaves removes all groups joined from the other origin with that execution
     77  // mode. Since clearOriginJoinedAdInterestGroups() only leaves interest
     78  // groups joined on the current origin, the executionMode should not matter.
     79  await joinInterestGroup(
     80      test, uuid,
     81      { name: 'group 1',
     82        executionMode: 'group-by-origin',
     83        biddingLogicURL: createBiddingScriptURL(
     84            { bid: 1, reportWin: `sendReportTo("${group1ReportURL}");`})});
     85  await joinInterestGroup(
     86      test, uuid,
     87      { name: 'group 2',
     88        biddingLogicURL: createBiddingScriptURL(
     89            { bid: 2, reportWin: `sendReportTo("${group2ReportURL}");`})});
     90  await joinInterestGroup(
     91      test, uuid,
     92      { name: 'group 3',
     93        executionMode: 'group-by-origin',
     94        biddingLogicURL: createBiddingScriptURL(
     95            { bid: 3, reportWin: `sendReportTo("${group3ReportURL}");`})});
     96 
     97  // Group 3 should win an auction, since it bids the most.
     98  await runBasicFledgeAuctionAndNavigate(test, uuid);
     99  await waitForObservedRequests(
    100      uuid, [group3ReportURL, createSellerReportURL(uuid)]);
    101  await fetch(createCleanupURL(uuid));
    102 
    103  // Clear, leaving group 1 in place, and run an auction, which group 1 should win.
    104  await navigator.clearOriginJoinedAdInterestGroups(
    105      window.location.origin, ['group 1']);
    106  await runBasicFledgeAuctionAndNavigate(test, uuid);
    107  await waitForObservedRequests(
    108      uuid, [group1ReportURL, createSellerReportURL(uuid)]);
    109 
    110  // Clear with an empty list, which should leave group 1 as well. Verify it can't
    111  // win an auction.
    112  await navigator.clearOriginJoinedAdInterestGroups(window.location.origin, []);
    113  await runBasicFledgeTestExpectingNoWinner(test, uuid);
    114 }, 'clearOriginJoinedAdInterestGroups(), multiple groups joined, group list.');
    115 
    116 subsetTest(promise_test, async test => {
    117  const uuid = generateUuid(test);
    118 
    119  // Join an interest group in a same-origin top-level window.
    120  await joinInterestGroupInTopLevelWindow(test, uuid, window.location.origin);
    121 
    122  // Make sure it was joined.
    123  await runBasicFledgeTestExpectingWinner(test, uuid);
    124 
    125  // Call "clearOriginJoinedAdInterestGroups()", which should leave the interest
    126  // group, since it was joined from a same-origin main frame.
    127  await navigator.clearOriginJoinedAdInterestGroups(window.location.origin);
    128 
    129  // Make sure group was left.
    130  await runBasicFledgeTestExpectingNoWinner(test, uuid);
    131 }, 'clearOriginJoinedAdInterestGroups(), group joined from same-origin top-level context.');
    132 
    133 subsetTest(promise_test, async test => {
    134  const uuid = generateUuid(test);
    135 
    136  // Create top-level browsing context for another origin, and have it join an
    137  // interest group owned by this document's origin.
    138  let topLevelWindow = await createTopLevelWindow(test, OTHER_ORIGIN1);
    139  let interestGroup = JSON.stringify(
    140      createInterestGroupForOrigin(uuid, window.location.origin));
    141  await runInFrame(test, topLevelWindow,
    142                   `await joinCrossOriginInterestGroup(test_instance, "${uuid}",
    143                                                       "${window.location.origin}",
    144                                                       ${interestGroup});`);
    145 
    146  // Call "clearOriginJoinedAdInterestGroups()", which should not leave the interest
    147  // group, since it was joined from a cross-origin main frame.
    148  await navigator.clearOriginJoinedAdInterestGroups(window.location.origin);
    149 
    150  // Make sure group was not left.
    151  await runBasicFledgeTestExpectingWinner(test, uuid);
    152 }, 'clearOriginJoinedAdInterestGroups(), group joined from cross-origin top-level context.');
    153 
    154 subsetTest(promise_test, async test => {
    155  const uuid = generateUuid(test);
    156 
    157  await joinInterestGroup(test, uuid);
    158 
    159  // In a cross-origin iframe, call clearOriginJoinedAdInterestGroups() both for the
    160  // iframe's origin and for the main frame's origin. The latter should throw an
    161  // exception, and neither should manage to leave the interest group.
    162  let iframe = await createIframe(test, OTHER_ORIGIN1, 'join-ad-interest-group');
    163  await runInFrame(test, iframe,
    164                   `// Call clearOriginJoinedAdInterestGroups() with the iframe's origin.
    165                    await navigator.clearOriginJoinedAdInterestGroups(window.location.origin);
    166                    try {
    167                      // Call clearOriginJoinedAdInterestGroups() with the main frame's origin.
    168                      await navigator.clearOriginJoinedAdInterestGroups("${window.location.origin}");
    169                    } catch (e) {
    170                      assert_true(e instanceof DOMException, "DOMException thrown");
    171                      assert_equals(e.name, "NotAllowedError", "NotAllowedError DOMException thrown");
    172                      return {result: "success"};
    173                    }
    174                    throw "Exception unexpectedly not thrown";`);
    175 
    176  // Confirm that the interest group was not left.
    177  await runBasicFledgeTestExpectingWinner(test, uuid);
    178 }, "clearOriginJoinedAdInterestGroups(), cross-origin iframe tries to leave parent frame's group.");
    179 
    180 subsetTest(promise_test, async test => {
    181  const uuid = generateUuid(test);
    182 
    183  // The possible results of calling clearOriginJoinedAdInterestGroups():
    184 
    185  // Doesn't throw an exception.
    186  const noExpectionURL = createTrackerURL(origin, uuid, "track_get", "no_exception");
    187  // Throws the exception it's expected to.
    188  const exceptionURL = createTrackerURL(origin, uuid, "track_get", "exception");
    189  // Throws the wrong exception.
    190  const badExpectionURL = createTrackerURL(origin, uuid, "track_get", "bad_exception");
    191 
    192  // Create a render URL that calls clearOriginJoinedAdInterestGroups() and
    193  // then requests one of the above tracking URLs, based on the resulting
    194  // behaviot.
    195  const renderURL = createRenderURL(
    196      uuid,
    197      `async function TryClear() {
    198         try {
    199           await navigator.clearOriginJoinedAdInterestGroups(
    200               "${window.location.origin}");
    201           await fetch("${noExpectionURL}");
    202         } catch (e) {
    203           if (e instanceof DOMException && e.name === "NotAllowedError") {
    204             await fetch("${exceptionURL}");
    205           } else {
    206             await fetch("${badExpectionURL}");
    207           }
    208         }
    209       }
    210 
    211       TryClear();`);
    212 
    213  await joinInterestGroup(
    214      test, uuid,
    215      {ads: [{ renderURL: renderURL}]});
    216 
    217  await runBasicFledgeAuctionAndNavigate(test, uuid);
    218 
    219  // This should wait until the clear call has thrown an exception.
    220  await waitForObservedRequests(
    221      uuid,
    222      [createBidderReportURL(uuid), createSellerReportURL(uuid), exceptionURL]);
    223 
    224  // Check the interest group was not left.
    225  await runBasicFledgeTestExpectingWinner(test, uuid);
    226 }, 'clearOriginJoinedAdInterestGroups() in ad fenced frame throws an exception.');
    227 
    228 ///////////////////////////////////////////////////////////////////////////////
    229 // Tests where some interest groups are owned by another origin.
    230 ///////////////////////////////////////////////////////////////////////////////
    231 
    232 subsetTest(promise_test, async test => {
    233  const uuid = generateUuid(test);
    234 
    235  // Join interest group in iframe and make sure it was joined.
    236  let iframe = await createIframe(test, OTHER_ORIGIN1, 'join-ad-interest-group');
    237  await runInFrame(test, iframe,
    238                   `await joinInterestGroup(test_instance, "${uuid}");
    239                    await runBasicFledgeTestExpectingWinner(test_instance, "${uuid}");`);
    240 
    241  // In the main frame, Call clearOriginJoinedAdInterestGroups() for both the main
    242  // frame's origin, and the origin of the iframe / joined interest group. Neither
    243  // should leave the group, and the second should throw.
    244  await navigator.clearOriginJoinedAdInterestGroups(window.location.origin);
    245  try {
    246    await navigator.clearOriginJoinedAdInterestGroups(OTHER_ORIGIN1);
    247    throw 'Exception unexpectedly not thrown';
    248  } catch (e) {
    249    if (!(e instanceof DOMException) || e.name !== 'NotAllowedError') {
    250      throw 'Wrong exception thrown: ' + e.toString();
    251    }
    252  }
    253 
    254  // In an iframe, confirm the group was never left.
    255  await runInFrame(test, iframe,
    256      `await runBasicFledgeTestExpectingWinner(test_instance, "${uuid}");`);
    257 }, 'clearOriginJoinedAdInterestGroups(). Cross-origin interest group joined in iframe, try to clear in main frame.');
    258 
    259 subsetTest(promise_test, async test => {
    260  const uuid = generateUuid(test);
    261 
    262  let iframe = await createIframe(test, OTHER_ORIGIN1, 'join-ad-interest-group');
    263  await runInFrame(test, iframe,
    264                   `await joinInterestGroup(test_instance, "${uuid}");
    265 
    266                    // Confirm that trying to clear the interest group using the main frame's
    267                    // origin throws, and does not leave the group.
    268                    try {
    269                      await navigator.clearOriginJoinedAdInterestGroups("${window.location.origin}");
    270                      throw 'Exception unexpectedly not thrown';
    271                    } catch (e) {
    272                      if (!(e instanceof DOMException) || e.name !== 'NotAllowedError') {
    273                        throw 'Wrong exception thrown: ' + e.toString();
    274                      }
    275                    }
    276                    await runBasicFledgeTestExpectingWinner(test_instance, "${uuid}");`);
    277 }, 'clearOriginJoinedAdInterestGroups(). Cross-origin interest group joined in iframe, clear call in iframe passing main frame origin.');
    278 
    279 subsetTest(promise_test, async test => {
    280  const uuid = generateUuid(test);
    281 
    282  let iframe = await createIframe(test, OTHER_ORIGIN1, 'join-ad-interest-group');
    283  await runInFrame(test, iframe,
    284                   `await joinInterestGroup(test_instance, "${uuid}");
    285 
    286                    // Clear call with the origin of the cross-origin iframe.
    287                    // This should successfully leave the interest group.
    288                    await navigator.clearOriginJoinedAdInterestGroups("${OTHER_ORIGIN1}");
    289 
    290                    // Verify the group was left.
    291                    await runBasicFledgeTestExpectingNoWinner(test_instance, "${uuid}");`);
    292 }, 'clearOriginJoinedAdInterestGroups(). Cross-origin interest group joined in iframe, clear call in iframe passing iframe origin.');
    293 
    294 subsetTest(promise_test, async test => {
    295  const uuid = generateUuid(test);
    296 
    297  // Join an OTHER_ORIGIN1 interest group in an OTHER_ORIGIN1 main frame.
    298  let topLevelWindow = await createTopLevelWindow(test, OTHER_ORIGIN1);
    299  await runInFrame(test, topLevelWindow,
    300                   `await joinInterestGroup(test_instance, "${uuid}");`);
    301 
    302  let iframe = await createIframe(test, OTHER_ORIGIN1, 'join-ad-interest-group');
    303 
    304  await runInFrame(test, iframe,
    305                   `// Clear call from an OTHER_ORIGIN1 iframe on a different
    306                    // origin's main frame. This should not clear the interest
    307                    // group that was just joined, because the joining origin
    308                    // does not match.
    309                    await navigator.clearOriginJoinedAdInterestGroups("${OTHER_ORIGIN1}");
    310 
    311                    // Verify the group was not left.
    312                    await runBasicFledgeTestExpectingWinner(test_instance, "${uuid}");`);
    313 }, 'clearOriginJoinedAdInterestGroups(). Cross-origin interest group joined from another joining origin, clear call in iframe.');