tor-browser

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

browser_abort_visibility.js (8464B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 const TEST_URL =
      8  "https://example.com/browser/dom/webauthn/tests/browser/tab_webauthn_result.html";
      9 
     10 add_task(async function test_setup() {
     11  return SpecialPowers.pushPrefEnv({
     12    set: [
     13      ["security.webauth.webauthn_enable_softtoken", false],
     14      ["security.webauth.webauthn_enable_usbtoken", true],
     15    ],
     16  });
     17 });
     18 add_task(test_switch_tab);
     19 add_task(test_new_window_make);
     20 add_task(test_new_window_get);
     21 add_task(test_minimize_make);
     22 add_task(test_minimize_get);
     23 
     24 async function assertStatus(tab, expected) {
     25  let actual = await SpecialPowers.spawn(
     26    tab.linkedBrowser,
     27    [],
     28    async function () {
     29      info("visbility state: " + content.document.visibilityState);
     30      info("active: " + content.browsingContext.isActive);
     31      return content.document.getElementById("status").value;
     32    }
     33  );
     34  is(actual, expected, "webauthn request " + expected);
     35 }
     36 
     37 async function waitForStatus(tab, expected) {
     38  /* eslint-disable no-shadow */
     39  await SpecialPowers.spawn(
     40    tab.linkedBrowser,
     41    [[expected]],
     42    async function (expected) {
     43      return ContentTaskUtils.waitForCondition(() => {
     44        info(
     45          "expecting " +
     46            expected +
     47            ", visbility state: " +
     48            content.document.visibilityState
     49        );
     50        info(
     51          "expecting " +
     52            expected +
     53            ", active: " +
     54            content.browsingContext.isActive
     55        );
     56        return content.document.getElementById("status").value == expected;
     57      });
     58    }
     59  );
     60  /* eslint-enable no-shadow */
     61 
     62  await assertStatus(tab, expected);
     63 }
     64 
     65 function startMakeCredentialRequest(tab) {
     66  return SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
     67    const cose_alg_ECDSA_w_SHA256 = -7;
     68 
     69    let publicKey = {
     70      rp: { id: content.document.domain, name: "none" },
     71      user: {
     72        id: new Uint8Array(),
     73        name: "none",
     74        displayName: "none",
     75      },
     76      challenge: content.crypto.getRandomValues(new Uint8Array(16)),
     77      timeout: 5000, // the minimum timeout is actually 15 seconds
     78      pubKeyCredParams: [{ type: "public-key", alg: cose_alg_ECDSA_w_SHA256 }],
     79    };
     80 
     81    let status = content.document.getElementById("status");
     82 
     83    info(
     84      "Attempting to create credential for origin: " +
     85        content.document.nodePrincipal.origin
     86    );
     87    content.navigator.credentials
     88      .create({ publicKey })
     89      .then(() => {
     90        status.value = "completed";
     91      })
     92      .catch(() => {
     93        status.value = "aborted";
     94      });
     95 
     96    status.value = "pending";
     97  });
     98 }
     99 
    100 function startGetAssertionRequest(tab) {
    101  return SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
    102    let newCredential = {
    103      type: "public-key",
    104      id: content.crypto.getRandomValues(new Uint8Array(16)),
    105      transports: ["usb"],
    106    };
    107 
    108    let publicKey = {
    109      challenge: content.crypto.getRandomValues(new Uint8Array(16)),
    110      timeout: 5000, // the minimum timeout is actually 15 seconds
    111      rpId: content.document.domain,
    112      allowCredentials: [newCredential],
    113    };
    114 
    115    let status = content.document.getElementById("status");
    116 
    117    info(
    118      "Attempting to get credential for origin: " +
    119        content.document.nodePrincipal.origin
    120    );
    121    content.navigator.credentials
    122      .get({ publicKey })
    123      .then(() => {
    124        status.value = "completed";
    125      })
    126      .catch(ex => {
    127        info("aborted: " + ex);
    128        status.value = "aborted";
    129      });
    130 
    131    status.value = "pending";
    132  });
    133 }
    134 
    135 // Test that MakeCredential() and GetAssertion() requests
    136 // are aborted when the current tab loses its focus.
    137 async function test_switch_tab() {
    138  // Create a new tab for the MakeCredential() request.
    139  let tab_create = await BrowserTestUtils.openNewForegroundTab(
    140    gBrowser,
    141    TEST_URL
    142  );
    143 
    144  // Start the request.
    145  await startMakeCredentialRequest(tab_create);
    146  await assertStatus(tab_create, "pending");
    147 
    148  // Open another tab and switch to it. The first will lose focus.
    149  let tab_get = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
    150  await assertStatus(tab_create, "pending");
    151 
    152  // Start a GetAssertion() request in the second tab, the first is aborted
    153  await startGetAssertionRequest(tab_get);
    154  await waitForStatus(tab_create, "aborted");
    155  await assertStatus(tab_get, "pending");
    156 
    157  // Start a second request in the second tab. It should abort.
    158  await startGetAssertionRequest(tab_get);
    159  await waitForStatus(tab_get, "aborted");
    160 
    161  // Close tabs.
    162  BrowserTestUtils.removeTab(tab_create);
    163  BrowserTestUtils.removeTab(tab_get);
    164 }
    165 
    166 function waitForWindowActive(win, active) {
    167  return Promise.all([
    168    BrowserTestUtils.waitForEvent(win, active ? "focus" : "blur"),
    169    BrowserTestUtils.waitForEvent(win, active ? "activate" : "deactivate"),
    170  ]);
    171 }
    172 
    173 async function test_new_window_make() {
    174  // Create a new tab for the MakeCredential() request.
    175  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
    176 
    177  // Start a MakeCredential request.
    178  await startMakeCredentialRequest(tab);
    179  await assertStatus(tab, "pending");
    180 
    181  let windowGonePromise = waitForWindowActive(window, false);
    182  // Open a new window. The tab will lose focus.
    183  let win = await BrowserTestUtils.openNewBrowserWindow();
    184  await windowGonePromise;
    185  await assertStatus(tab, "pending");
    186 
    187  let windowBackPromise = waitForWindowActive(window, true);
    188  await BrowserTestUtils.closeWindow(win);
    189  await windowBackPromise;
    190 
    191  // Close tab.
    192  await BrowserTestUtils.removeTab(tab);
    193 }
    194 
    195 async function test_new_window_get() {
    196  // Create a new tab for the GetAssertion() request.
    197  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
    198 
    199  // Start a GetAssertion request.
    200  await startGetAssertionRequest(tab);
    201  await assertStatus(tab, "pending");
    202 
    203  let windowGonePromise = waitForWindowActive(window, false);
    204  // Open a new window. The tab will lose focus.
    205  let win = await BrowserTestUtils.openNewBrowserWindow();
    206  await windowGonePromise;
    207  await assertStatus(tab, "pending");
    208 
    209  let windowBackPromise = waitForWindowActive(window, true);
    210  await BrowserTestUtils.closeWindow(win);
    211  await windowBackPromise;
    212 
    213  // Close tab.
    214  BrowserTestUtils.removeTab(tab);
    215 }
    216 
    217 async function test_minimize_make() {
    218  // Minimizing windows doesn't supported in headless mode.
    219  if (Services.env.get("MOZ_HEADLESS")) {
    220    return;
    221  }
    222 
    223  // Create a new window for the MakeCredential() request.
    224  let win = await BrowserTestUtils.openNewBrowserWindow();
    225  let tab = await BrowserTestUtils.openNewForegroundTab(win.gBrowser, TEST_URL);
    226 
    227  // Start a MakeCredential request.
    228  await startMakeCredentialRequest(tab);
    229  await assertStatus(tab, "pending");
    230 
    231  // Minimize the window.
    232  let windowGonePromise = waitForWindowActive(win, false);
    233  win.minimize();
    234  await assertStatus(tab, "pending");
    235  await windowGonePromise;
    236 
    237  // Restore the window.
    238  await new Promise(resolve => SimpleTest.waitForFocus(resolve, win));
    239  await assertStatus(tab, "pending");
    240 
    241  // Close window and wait for main window to be focused again.
    242  let windowBackPromise = waitForWindowActive(window, true);
    243  await BrowserTestUtils.removeTab(tab);
    244  await BrowserTestUtils.closeWindow(win);
    245  await windowBackPromise;
    246 }
    247 
    248 async function test_minimize_get() {
    249  // Minimizing windows doesn't supported in headless mode.
    250  if (Services.env.get("MOZ_HEADLESS")) {
    251    return;
    252  }
    253 
    254  // Create a new window for the GetAssertion() request.
    255  let win = await BrowserTestUtils.openNewBrowserWindow();
    256  let tab = await BrowserTestUtils.openNewForegroundTab(win.gBrowser, TEST_URL);
    257 
    258  // Start a GetAssertion request.
    259  await startGetAssertionRequest(tab);
    260  await assertStatus(tab, "pending");
    261 
    262  // Minimize the window.
    263  let windowGonePromise = waitForWindowActive(win, false);
    264  win.minimize();
    265  await assertStatus(tab, "pending");
    266  await windowGonePromise;
    267 
    268  // Restore the window.
    269  await new Promise(resolve => SimpleTest.waitForFocus(resolve, win));
    270  await assertStatus(tab, "pending");
    271 
    272  // Close window and wait for main window to be focused again.
    273  let windowBackPromise = waitForWindowActive(window, true);
    274  await BrowserTestUtils.removeTab(tab);
    275  await BrowserTestUtils.closeWindow(win);
    276  await windowBackPromise;
    277 }