tor-browser

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

rejects_if_not_active.https.html (5080B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8" />
      3 <title>PaymentRequest show() rejects if doc is not fully active</title>
      4 <link rel="help" href="https://w3c.github.io/payment-request/#show-method" />
      5 <script src="/resources/testharness.js"></script>
      6 <script src="/resources/testharnessreport.js"></script>
      7 <script src="/resources/testdriver.js"></script>
      8 <script src="/resources/testdriver-vendor.js"></script>
      9 <body>
     10  <script>
     11    const applePay = Object.freeze({
     12      supportedMethods: "https://apple.com/apple-pay",
     13      data: {
     14        version: 3,
     15        merchantIdentifier: "merchant.com.example",
     16        countryCode: "US",
     17        merchantCapabilities: ["supports3DS"],
     18        supportedNetworks: ["visa"],
     19      },
     20    });
     21    const validMethod = Object.freeze({
     22      supportedMethods: "basic-card",
     23    });
     24    const validMethods = Object.freeze([validMethod, applePay]);
     25 
     26    const validDetails = Object.freeze({
     27      total: {
     28        label: "Total due",
     29        amount: {
     30          currency: "USD",
     31          value: "5.00",
     32        },
     33      },
     34    });
     35 
     36    async function getLoadedPaymentRequest(iframe, url) {
     37      await new Promise((resolve) => {
     38        iframe.addEventListener("load", resolve, { once: true });
     39        iframe.src = url;
     40      });
     41      return new iframe.contentWindow.PaymentRequest(
     42        validMethods,
     43        validDetails
     44      );
     45    }
     46 
     47    promise_test(async (t) => {
     48      const iframe = document.createElement("iframe");
     49      iframe.allow = "payment";
     50      document.body.appendChild(iframe);
     51      t.add_cleanup(() => {
     52        iframe.remove();
     53      });
     54      // We first got to page1.html, grab a PaymentRequest instance.
     55      const request1 = await getLoadedPaymentRequest(
     56        iframe,
     57        "./resources/page1.html"
     58      );
     59      // Save the DOMException of page1.html before navigating away.
     60      const frameDOMException1 = iframe.contentWindow.DOMException;
     61 
     62      // Get transient activation
     63      await test_driver.bless("payment 1", () => {}, iframe.contentWindow);
     64 
     65      // We navigate the iframe again, putting request1's document into an non-fully active state.
     66      const request2 = await getLoadedPaymentRequest(
     67        iframe,
     68        "./resources/page2.html"
     69      );
     70 
     71      // Now, request1's relevant global object's document is no longer active.
     72      // So, call .show(), and make sure it rejects appropriately.
     73      await promise_rejects_dom(
     74        t,
     75        "AbortError",
     76        frameDOMException1,
     77        request1.show(),
     78        "Inactive document, so must throw AbortError"
     79      );
     80      // request2 has an active document tho, so confirm it's working as expected:
     81      // Get transient activation
     82      await test_driver.bless("payment 2", () => {}, iframe.contentWindow);
     83      request2.show();
     84      await request2.abort();
     85      await promise_rejects_dom(
     86        t,
     87        "InvalidStateError",
     88        iframe.contentWindow.DOMException,
     89        request2.show(),
     90        "Abort already called, so InvalidStateError"
     91      );
     92    }, "PaymentRequest.show() aborts if the document is not active.");
     93 
     94    promise_test(async (t) => {
     95      // We nest two iframes and wait for them to load.
     96      const outerIframe = document.createElement("iframe");
     97      outerIframe.allow = "payment";
     98      document.body.appendChild(outerIframe);
     99      t.add_cleanup(() => {
    100        outerIframe.remove();
    101      });
    102      // Load the outer iframe (we don't care about the awaited request)
    103      await getLoadedPaymentRequest(outerIframe, "./resources/page1.html");
    104 
    105      // Now we create the inner iframe
    106      const innerIframe = outerIframe.contentDocument.createElement("iframe");
    107      innerIframe.allow = "payment";
    108 
    109      // nest them
    110      outerIframe.contentDocument.body.appendChild(innerIframe);
    111 
    112      // load innerIframe, and get the PaymentRequest instance
    113      const request = await getLoadedPaymentRequest(
    114        innerIframe,
    115        "./resources/page2.html"
    116      );
    117      // Save DOMException from innerIframe before navigating away.
    118      const innerIframeDOMException = innerIframe.contentWindow.DOMException;
    119 
    120      // Navigate the outer iframe to a new location.
    121      // Wait for the load event to fire.
    122      await new Promise((resolve) => {
    123        outerIframe.addEventListener("load", resolve);
    124        outerIframe.src = "./resources/page2.html";
    125      });
    126 
    127      await test_driver.bless("", () => {}, innerIframe.contentWindow);
    128      const showPromise = request.show();
    129      // Now, request's relevant global object's document is still active
    130      // (it is the active document of the inner iframe), but is not fully active
    131      // (since the parent of the inner iframe is itself no longer active).
    132      // So, call request.show() and make sure it rejects appropriately.
    133      await promise_rejects_dom(
    134        t,
    135        "AbortError",
    136        innerIframeDOMException,
    137        showPromise,
    138        "Active, but not fully active, so must throw AbortError"
    139      );
    140    }, "PaymentRequest.show() aborts if the document is active, but not fully active.");
    141  </script>
    142 </body>