/* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; const TEST_URI_FIRST_PARTY = "https://example.com"; const TEST_URI_THIRD_PARTY = "https://itisatracker.org"; const LEARN_MORE_URI = "https://developer.mozilla.org/docs/Web/API/Document/requestStorageAccess" + DOCS_GA_PARAMS; /** * Run document.requestStorageAccess in an iframe. * * @param {object} options - Request / iframe options. * @param {boolean} [options.withUserActivation] - Whether the requesting iframe * should have user activation prior to calling rsA. * @param {string} [options.sandboxAttr] - Iframe sandbox attributes. * @param {boolean} [options.nested] - If the iframe calling rsA should be * nested in another same-origin iframe. */ async function runRequestStorageAccess({ withUserActivation = false, sandboxAttr = "", nested = false, }) { let parentBC = gBrowser.selectedBrowser.browsingContext; // Spawn the rsA iframe in an iframe. if (nested) { parentBC = await SpecialPowers.spawn( parentBC, [TEST_URI_THIRD_PARTY], async uri => { const frame = content.document.createElement("iframe"); frame.setAttribute("src", uri); const loadPromise = ContentTaskUtils.waitForEvent(frame, "load"); content.document.body.appendChild(frame); await loadPromise; return frame.browsingContext; } ); } // Create an iframe which is a third party to the top level. const frameBC = await SpecialPowers.spawn( parentBC, [TEST_URI_THIRD_PARTY, sandboxAttr], async (uri, sandbox) => { const frame = content.document.createElement("iframe"); frame.setAttribute("src", uri); if (sandbox) { frame.setAttribute("sandbox", sandbox); } const loadPromise = ContentTaskUtils.waitForEvent(frame, "load"); content.document.body.appendChild(frame); await loadPromise; return frame.browsingContext; } ); // Call requestStorageAccess in the iframe. await SpecialPowers.spawn(frameBC, [withUserActivation], userActivation => { if (userActivation) { content.document.notifyUserGestureActivation(); } content.document.requestStorageAccess(); }); } add_task(async function () { await setupUrlClassifierTest({ enableTrackingProtection: false }); const hud = await openNewTabAndConsole(TEST_URI_FIRST_PARTY); async function checkErrorMessage(text) { const message = await waitFor( () => findErrorMessage(hud, text), undefined, 100 ); ok(true, "Error message is visible: " + text); const checkLink = ({ link, where, expectedLink, expectedTab }) => { is(link, expectedLink, `Clicking the provided link opens ${link}`); is( where, expectedTab, `Clicking the provided link opens in expected tab` ); }; info("Clicking on the Learn More link"); const learnMoreLink = message.querySelector(".learn-more-link"); const linkSimulation = await simulateLinkClick(learnMoreLink); checkLink({ ...linkSimulation, expectedLink: LEARN_MORE_URI, expectedTab: "tab", }); } const userGesture = "document.requestStorageAccess() may only be requested from inside a short running user-generated event handler"; const nullPrincipal = "document.requestStorageAccess() may not be called on a document with an opaque origin, such as a sandboxed iframe without allow-same-origin in its sandbox attribute."; const sandboxed = "document.requestStorageAccess() may not be called in a sandboxed iframe without allow-storage-access-by-user-activation in its sandbox attribute."; await runRequestStorageAccess({ withUserActivation: false }); await checkErrorMessage(userGesture); await runRequestStorageAccess({ withUserActivation: true, sandboxAttr: "allow-scripts", }); await checkErrorMessage(nullPrincipal); await runRequestStorageAccess({ withUserActivation: true, sandboxAttr: "allow-same-origin allow-scripts", }); await checkErrorMessage(sandboxed); await closeConsole(); });