| // META: script=/resources/testdriver.js |
| // META: script=/common/utils.js |
| // META: script=resources/fledge-util.sub.js |
| // META: script=/common/subset-tests.js |
| // META: timeout=long |
| // META: variant=?1-4 |
| // META: variant=?5-8 |
| // META: variant=?9-12 |
| // META: variant=?13-last |
| |
| "use strict;" |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // Basic tests with no interest groups joined. |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| subsetTest(promise_test, async test => { |
| await navigator.clearOriginJoinedAdInterestGroups(window.location.origin); |
| }, 'clearOriginJoinedAdInterestGroups(), no groups joined, no group list.'); |
| |
| subsetTest(promise_test, async test => { |
| await navigator.clearOriginJoinedAdInterestGroups(window.location.origin, []); |
| }, 'clearOriginJoinedAdInterestGroups(), no groups joined, group list.'); |
| |
| subsetTest(promise_test, async test => { |
| try { |
| await navigator.clearOriginJoinedAdInterestGroups(OTHER_ORIGIN1); |
| throw 'Exception unexpectedly not thrown'; |
| } catch (e) { |
| if (!(e instanceof DOMException) || e.name !== 'NotAllowedError') { |
| throw 'Wrong exception thrown: ' + e.toString(); |
| } |
| } |
| }, 'clearOriginJoinedAdInterestGroups(), cross-origin, no groups joined, no group list.'); |
| |
| subsetTest(promise_test, async test => { |
| try { |
| await navigator.clearOriginJoinedAdInterestGroups(OTHER_ORIGIN1, []); |
| throw 'Exception unexpectedly not thrown'; |
| } catch (e) { |
| if (!(e instanceof DOMException) || e.name !== 'NotAllowedError') { |
| throw 'Wrong exception thrown: ' + e.toString(); |
| } |
| } |
| }, 'clearOriginJoinedAdInterestGroups(), cross-origin, no groups joined, group list.'); |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // Tests where interest groups are all owned by document.location.origin. |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| subsetTest(promise_test, async test => { |
| const uuid = generateUuid(test); |
| |
| // Join 3 groups. |
| await joinInterestGroup(test, uuid); |
| await joinInterestGroup(test, uuid, {name: 'group 2'}); |
| await joinInterestGroup(test, uuid, {name: 'group 3'}); |
| |
| // A single clear should leave them all. |
| await navigator.clearOriginJoinedAdInterestGroups(window.location.origin); |
| |
| // Confirm that they were left. |
| await runBasicFledgeTestExpectingNoWinner(test, uuid); |
| }, 'clearOriginJoinedAdInterestGroups(), multiple groups joined, no group list.'); |
| |
| subsetTest(promise_test, async test => { |
| const uuid = generateUuid(test); |
| |
| let group1ReportURL = createBidderReportURL(uuid, /*id=*/'1'); |
| let group2ReportURL = createBidderReportURL(uuid, /*id=*/'2'); |
| let group3ReportURL = createBidderReportURL(uuid, /*id=*/'3'); |
| |
| // Join 3 groups, with distinct report URLs and increasing bid amounts. |
| // Set "executionMode" to "group-by-origin" for two of them, since cross-origin |
| // leaves removes all groups joined from the other origin with that execution |
| // mode. Since clearOriginJoinedAdInterestGroups() only leaves interest |
| // groups joined on the current origin, the executionMode should not matter. |
| await joinInterestGroup( |
| test, uuid, |
| { name: 'group 1', |
| executionMode: 'group-by-origin', |
| biddingLogicURL: createBiddingScriptURL( |
| { bid: 1, reportWin: `sendReportTo("${group1ReportURL}");`})}); |
| await joinInterestGroup( |
| test, uuid, |
| { name: 'group 2', |
| biddingLogicURL: createBiddingScriptURL( |
| { bid: 2, reportWin: `sendReportTo("${group2ReportURL}");`})}); |
| await joinInterestGroup( |
| test, uuid, |
| { name: 'group 3', |
| executionMode: 'group-by-origin', |
| biddingLogicURL: createBiddingScriptURL( |
| { bid: 3, reportWin: `sendReportTo("${group3ReportURL}");`})}); |
| |
| // Group 3 should win an auction, since it bids the most. |
| await runBasicFledgeAuctionAndNavigate(test, uuid); |
| await waitForObservedRequests( |
| uuid, [group3ReportURL, createSellerReportURL(uuid)]); |
| await fetch(createCleanupURL(uuid)); |
| |
| // Clear, leaving group 1 in place, and run an auction, which group 1 should win. |
| await navigator.clearOriginJoinedAdInterestGroups( |
| window.location.origin, ['group 1']); |
| await runBasicFledgeAuctionAndNavigate(test, uuid); |
| await waitForObservedRequests( |
| uuid, [group1ReportURL, createSellerReportURL(uuid)]); |
| |
| // Clear with an empty list, which should leave group 1 as well. Verify it can't |
| // win an auction. |
| await navigator.clearOriginJoinedAdInterestGroups(window.location.origin, []); |
| await runBasicFledgeTestExpectingNoWinner(test, uuid); |
| }, 'clearOriginJoinedAdInterestGroups(), multiple groups joined, group list.'); |
| |
| subsetTest(promise_test, async test => { |
| const uuid = generateUuid(test); |
| |
| // Join an interest group in a same-origin top-level window. |
| await joinInterestGroupInTopLevelWindow(test, uuid, window.location.origin); |
| |
| // Make sure it was joined. |
| await runBasicFledgeTestExpectingWinner(test, uuid); |
| |
| // Call "clearOriginJoinedAdInterestGroups()", which should leave the interest |
| // group, since it was joined from a same-origin main frame. |
| await navigator.clearOriginJoinedAdInterestGroups(window.location.origin); |
| |
| // Make sure group was left. |
| await runBasicFledgeTestExpectingNoWinner(test, uuid); |
| }, 'clearOriginJoinedAdInterestGroups(), group joined from same-origin top-level context.'); |
| |
| subsetTest(promise_test, async test => { |
| const uuid = generateUuid(test); |
| |
| // Create top-level browsing context for another origin, and have it join an |
| // interest group owned by this document's origin. |
| let topLevelWindow = await createTopLevelWindow(test, OTHER_ORIGIN1); |
| let interestGroup = JSON.stringify( |
| createInterestGroupForOrigin(uuid, window.location.origin)); |
| await runInFrame(test, topLevelWindow, |
| `await joinCrossOriginInterestGroup(test_instance, "${uuid}", |
| "${window.location.origin}", |
| ${interestGroup});`); |
| |
| // Call "clearOriginJoinedAdInterestGroups()", which should not leave the interest |
| // group, since it was joined from a cross-origin main frame. |
| await navigator.clearOriginJoinedAdInterestGroups(window.location.origin); |
| |
| // Make sure group was not left. |
| await runBasicFledgeTestExpectingWinner(test, uuid); |
| }, 'clearOriginJoinedAdInterestGroups(), group joined from cross-origin top-level context.'); |
| |
| subsetTest(promise_test, async test => { |
| const uuid = generateUuid(test); |
| |
| await joinInterestGroup(test, uuid); |
| |
| // In a cross-origin iframe, call clearOriginJoinedAdInterestGroups() both for the |
| // iframe's origin and for the main frame's origin. The latter should throw an |
| // exception, and neither should manage to leave the interest group. |
| let iframe = await createIframe(test, OTHER_ORIGIN1, 'join-ad-interest-group'); |
| await runInFrame(test, iframe, |
| `// Call clearOriginJoinedAdInterestGroups() with the iframe's origin. |
| await navigator.clearOriginJoinedAdInterestGroups(window.location.origin); |
| try { |
| // Call clearOriginJoinedAdInterestGroups() with the main frame's origin. |
| await navigator.clearOriginJoinedAdInterestGroups("${window.location.origin}"); |
| } catch (e) { |
| assert_true(e instanceof DOMException, "DOMException thrown"); |
| assert_equals(e.name, "NotAllowedError", "NotAllowedError DOMException thrown"); |
| return {result: "success"}; |
| } |
| throw "Exception unexpectedly not thrown";`); |
| |
| // Confirm that the interest group was not left. |
| await runBasicFledgeTestExpectingWinner(test, uuid); |
| }, "clearOriginJoinedAdInterestGroups(), cross-origin iframe tries to leave parent frame's group."); |
| |
| subsetTest(promise_test, async test => { |
| const uuid = generateUuid(test); |
| |
| // The possible results of calling clearOriginJoinedAdInterestGroups(): |
| |
| // Doesn't throw an exception. |
| const noExpectionURL = createTrackerURL(origin, uuid, "track_get", "no_exception"); |
| // Throws the exception it's expected to. |
| const exceptionURL = createTrackerURL(origin, uuid, "track_get", "exception"); |
| // Throws the wrong exception. |
| const badExpectionURL = createTrackerURL(origin, uuid, "track_get", "bad_exception"); |
| |
| // Create a render URL that calls clearOriginJoinedAdInterestGroups() and |
| // then requests one of the above tracking URLs, based on the resulting |
| // behaviot. |
| const renderURL = createRenderURL( |
| uuid, |
| `async function TryClear() { |
| try { |
| await navigator.clearOriginJoinedAdInterestGroups( |
| "${window.location.origin}"); |
| await fetch("${noExpectionURL}"); |
| } catch (e) { |
| if (e instanceof DOMException && e.name === "NotAllowedError") { |
| await fetch("${exceptionURL}"); |
| } else { |
| await fetch("${badExpectionURL}"); |
| } |
| } |
| } |
| |
| TryClear();`); |
| |
| await joinInterestGroup( |
| test, uuid, |
| {ads: [{ renderURL: renderURL}]}); |
| |
| await runBasicFledgeAuctionAndNavigate(test, uuid); |
| |
| // This should wait until the clear call has thrown an exception. |
| await waitForObservedRequests( |
| uuid, |
| [createBidderReportURL(uuid), createSellerReportURL(uuid), exceptionURL]); |
| |
| // Check the interest group was not left. |
| await runBasicFledgeTestExpectingWinner(test, uuid); |
| }, 'clearOriginJoinedAdInterestGroups() in ad fenced frame throws an exception.'); |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // Tests where some interest groups are owned by another origin. |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| subsetTest(promise_test, async test => { |
| const uuid = generateUuid(test); |
| |
| // Join interest group in iframe and make sure it was joined. |
| let iframe = await createIframe(test, OTHER_ORIGIN1, 'join-ad-interest-group'); |
| await runInFrame(test, iframe, |
| `await joinInterestGroup(test_instance, "${uuid}"); |
| await runBasicFledgeTestExpectingWinner(test_instance, "${uuid}");`); |
| |
| // In the main frame, Call clearOriginJoinedAdInterestGroups() for both the main |
| // frame's origin, and the origin of the iframe / joined interest group. Neither |
| // should leave the group, and the second should throw. |
| await navigator.clearOriginJoinedAdInterestGroups(window.location.origin); |
| try { |
| await navigator.clearOriginJoinedAdInterestGroups(OTHER_ORIGIN1); |
| throw 'Exception unexpectedly not thrown'; |
| } catch (e) { |
| if (!(e instanceof DOMException) || e.name !== 'NotAllowedError') { |
| throw 'Wrong exception thrown: ' + e.toString(); |
| } |
| } |
| |
| // In an iframe, confirm the group was never left. |
| await runInFrame(test, iframe, |
| `await runBasicFledgeTestExpectingWinner(test_instance, "${uuid}");`); |
| }, 'clearOriginJoinedAdInterestGroups(). Cross-origin interest group joined in iframe, try to clear in main frame.'); |
| |
| subsetTest(promise_test, async test => { |
| const uuid = generateUuid(test); |
| |
| let iframe = await createIframe(test, OTHER_ORIGIN1, 'join-ad-interest-group'); |
| await runInFrame(test, iframe, |
| `await joinInterestGroup(test_instance, "${uuid}"); |
| |
| // Confirm that trying to clear the interest group using the main frame's |
| // origin throws, and does not leave the group. |
| try { |
| await navigator.clearOriginJoinedAdInterestGroups("${window.location.origin}"); |
| throw 'Exception unexpectedly not thrown'; |
| } catch (e) { |
| if (!(e instanceof DOMException) || e.name !== 'NotAllowedError') { |
| throw 'Wrong exception thrown: ' + e.toString(); |
| } |
| } |
| await runBasicFledgeTestExpectingWinner(test_instance, "${uuid}");`); |
| }, 'clearOriginJoinedAdInterestGroups(). Cross-origin interest group joined in iframe, clear call in iframe passing main frame origin.'); |
| |
| subsetTest(promise_test, async test => { |
| const uuid = generateUuid(test); |
| |
| let iframe = await createIframe(test, OTHER_ORIGIN1, 'join-ad-interest-group'); |
| await runInFrame(test, iframe, |
| `await joinInterestGroup(test_instance, "${uuid}"); |
| |
| // Clear call with the origin of the cross-origin iframe. |
| // This should successfully leave the interest group. |
| await navigator.clearOriginJoinedAdInterestGroups("${OTHER_ORIGIN1}"); |
| |
| // Verify the group was left. |
| await runBasicFledgeTestExpectingNoWinner(test_instance, "${uuid}");`); |
| }, 'clearOriginJoinedAdInterestGroups(). Cross-origin interest group joined in iframe, clear call in iframe passing iframe origin.'); |
| |
| subsetTest(promise_test, async test => { |
| const uuid = generateUuid(test); |
| |
| // Join an OTHER_ORIGIN1 interest group in an OTHER_ORIGIN1 main frame. |
| let topLevelWindow = await createTopLevelWindow(test, OTHER_ORIGIN1); |
| await runInFrame(test, topLevelWindow, |
| `await joinInterestGroup(test_instance, "${uuid}");`); |
| |
| let iframe = await createIframe(test, OTHER_ORIGIN1, 'join-ad-interest-group'); |
| |
| await runInFrame(test, iframe, |
| `// Clear call from an OTHER_ORIGIN1 iframe on a different |
| // origin's main frame. This should not clear the interest |
| // group that was just joined, because the joining origin |
| // does not match. |
| await navigator.clearOriginJoinedAdInterestGroups("${OTHER_ORIGIN1}"); |
| |
| // Verify the group was not left. |
| await runBasicFledgeTestExpectingWinner(test_instance, "${uuid}");`); |
| }, 'clearOriginJoinedAdInterestGroups(). Cross-origin interest group joined from another joining origin, clear call in iframe.'); |