tor-browser

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

browser_captivePortal_trr_mode3.js (6380B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 let gServer;
      7 let gServerURL;
      8 let gRedirectedURL;
      9 let gExpectedText;
     10 let gNavigated = false;
     11 let gExpectedURL;
     12 
     13 const { HttpServer } = ChromeUtils.importESModule(
     14  "resource://testing-common/httpd.sys.mjs"
     15 );
     16 
     17 const gOverride = Cc["@mozilla.org/network/native-dns-override;1"].getService(
     18  Ci.nsINativeDNSResolverOverride
     19 );
     20 
     21 let gCaptivePortalState = "captive-replace";
     22 
     23 add_setup(async function () {
     24  gOverride.addIPOverride("test1.example.com", "127.0.0.1");
     25  gOverride.addIPOverride("example.net", "127.0.0.1");
     26  gServer = new HttpServer();
     27  gServer.start(-1);
     28  // eslint-disable-next-line @microsoft/sdl/no-insecure-url
     29  gServerURL = `http://test1.example.com:${gServer.identity.primaryPort}/`;
     30  // eslint-disable-next-line @microsoft/sdl/no-insecure-url
     31  gRedirectedURL = `http://example.net:${gServer.identity.primaryPort}/redir`;
     32  gServer.identity.add(
     33    "http",
     34    "test1.example.com",
     35    gServer.identity.primaryPort
     36  );
     37  gServer.identity.add("http", "example.net", gServer.identity.primaryPort);
     38  gServer.registerPathHandler("/", (request, response) => {
     39    if (gCaptivePortalState == "captive-replace") {
     40      response.setStatusLine(request.httpVersion, 200, "OK");
     41      response.setHeader("Content-Type", "text/html");
     42      const BODY = `captive muahahah`;
     43      response.bodyOutputStream.write(BODY, BODY.length);
     44      return;
     45    }
     46 
     47    if (gCaptivePortalState == "captive-redirect") {
     48      response.setStatusLine(request.httpVersion, 302, "Moved Temporarily");
     49      // eslint-disable-next-line @microsoft/sdl/no-insecure-url
     50      response.setHeader("Location", gRedirectedURL);
     51      response.write("redirecting");
     52    }
     53  });
     54  gServer.registerPathHandler("/redir", (request, response) => {
     55    response.setStatusLine(request.httpVersion, 200, "OK");
     56    response.setHeader("Content-Type", "text/html");
     57    const BODY = `redirected`;
     58    response.bodyOutputStream.write(BODY, BODY.length);
     59  });
     60  registerCleanupFunction(async () => {
     61    await gServer.stop();
     62    gOverride.clearOverrides();
     63  });
     64 
     65  await SpecialPowers.pushPrefEnv({
     66    set: [
     67      ["test.wait300msAfterTabSwitch", true],
     68      ["captivedetect.canonicalURL", gServerURL],
     69      ["captivedetect.canonicalContent", "stuff"],
     70      ["network.trr.mode", Ci.nsIDNSService.MODE_TRRONLY],
     71      ["network.proxy.no_proxies_on", "test1.example.com,example.net"],
     72    ],
     73  });
     74 });
     75 
     76 async function openAndCheck() {
     77  // Open a second window in the background. Later, we'll check that
     78  // when we click the button to open the captive portal tab, the tab
     79  // only opens in the active window and not in the background one.
     80  let secondWindow = await openWindowAndWaitForFocus();
     81  await SimpleTest.promiseFocus(window);
     82 
     83  await portalDetected();
     84 
     85  // Check that we didn't open anything in the background window.
     86  ensureNoPortalTab(secondWindow);
     87 
     88  let tab = await openCaptivePortalErrorTab();
     89  let browser = tab.linkedBrowser;
     90  let portalTabPromise = BrowserTestUtils.waitForNewTab(gBrowser, gExpectedURL);
     91 
     92  await SpecialPowers.spawn(browser, [], async () => {
     93    let doc = content.document;
     94    let loginButton = doc.getElementById("openPortalLoginPageButton");
     95    await ContentTaskUtils.waitForCondition(
     96      () => ContentTaskUtils.isVisible(loginButton),
     97      "Captive portal error page UI is visible"
     98    );
     99 
    100    if (!Services.focus.focusedElement == loginButton) {
    101      await ContentTaskUtils.waitForEvent(loginButton, "focus");
    102    }
    103 
    104    Assert.ok(true, "openPortalLoginPageButton has focus");
    105    info("Clicking the Open Login Page button");
    106    await EventUtils.synthesizeMouseAtCenter(loginButton, {}, content);
    107  });
    108 
    109  let portalTab = await portalTabPromise;
    110  await SpecialPowers.spawn(
    111    portalTab.linkedBrowser,
    112    [gExpectedText],
    113    async text => {
    114      Assert.equal(content.document.body.innerText, text);
    115    }
    116  );
    117 
    118  is(
    119    gBrowser.selectedTab,
    120    portalTab,
    121    "Login page should be open in a new foreground tab."
    122  );
    123 
    124  // Check that we didn't open anything in the background window.
    125  ensureNoPortalTab(secondWindow);
    126 
    127  // Make sure clicking the "Open Login Page" button again focuses the existing portal tab.
    128  await BrowserTestUtils.switchTab(gBrowser, tab);
    129  // Passing an empty function to BrowserTestUtils.switchTab lets us wait for an arbitrary
    130  // tab switch.
    131  portalTabPromise = BrowserTestUtils.switchTab(gBrowser, () => {});
    132  await SpecialPowers.spawn(browser, [], async () => {
    133    info("Clicking the Open Login Page button.");
    134    let loginButton = content.document.getElementById(
    135      "openPortalLoginPageButton"
    136    );
    137    await EventUtils.synthesizeMouseAtCenter(loginButton, {}, content);
    138  });
    139 
    140  info("Opening captive portal login page");
    141  let portalTab2 = await portalTabPromise;
    142  is(portalTab2, portalTab, "The existing portal tab should be focused.");
    143 
    144  // Check that we didn't open anything in the background window.
    145  ensureNoPortalTab(secondWindow);
    146 
    147  let portalTabClosing = BrowserTestUtils.waitForTabClosing(portalTab);
    148  let errorTabReloaded = BrowserTestUtils.waitForErrorPage(browser);
    149 
    150  Services.obs.notifyObservers(null, "captive-portal-login-success");
    151  info("closing page");
    152  if (gNavigated) {
    153    // Since it navigated, the tab won't be automatically closed.
    154    await BrowserTestUtils.removeTab(portalTab);
    155  }
    156 
    157  await portalTabClosing;
    158 
    159  info(
    160    "Waiting for error tab to be reloaded after the captive portal was freed."
    161  );
    162  await errorTabReloaded;
    163  await SpecialPowers.spawn(browser, [], () => {
    164    let doc = content.document;
    165    ok(
    166      !doc.body.classList.contains("captiveportal"),
    167      "Captive portal error page UI is not visible."
    168    );
    169  });
    170 
    171  await BrowserTestUtils.removeTab(tab);
    172  await BrowserTestUtils.closeWindow(secondWindow);
    173 }
    174 
    175 add_task(async function checkNoTRRForTab() {
    176  info("Check that the captive portal login tab does not use TRR");
    177  gExpectedText = `captive muahahah`;
    178  gExpectedURL = gServerURL;
    179 
    180  await openAndCheck();
    181 });
    182 
    183 add_task(async function checkNoTRRForTabWithRedirect() {
    184  gCaptivePortalState = "captive-redirect";
    185  gExpectedText = "redirected";
    186  gExpectedURL = gRedirectedURL;
    187  gNavigated = true;
    188  info("Check that the captive portal login tab does not use TRR");
    189 
    190  await openAndCheck();
    191 });