tor-browser

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

browser_refreshBlocker.js (6770B)


      1 "use strict";
      2 
      3 const META_PAGE =
      4  // eslint-disable-next-line @microsoft/sdl/no-insecure-url
      5  "http://example.org/browser/browser/base/content/test/general/refresh_meta.sjs";
      6 const HEADER_PAGE =
      7  // eslint-disable-next-line @microsoft/sdl/no-insecure-url
      8  "http://example.org/browser/browser/base/content/test/general/refresh_header.sjs";
      9 const TARGET_PAGE =
     10  // eslint-disable-next-line @microsoft/sdl/no-insecure-url
     11  "http://example.org/browser/browser/base/content/test/general/dummy_page.html";
     12 const PREF = "accessibility.blockautorefresh";
     13 
     14 /**
     15 * Goes into the content, and simulates a meta-refresh header at a very
     16 * low level, and checks to see if it was blocked. This will always cancel
     17 * the refresh, regardless of whether or not the refresh was blocked.
     18 *
     19 * @param browser (<xul:browser>)
     20 *        The browser to test for refreshing.
     21 * @param expectRefresh (bool)
     22 *        Whether or not we expect the refresh attempt to succeed.
     23 * @returns Promise
     24 */
     25 async function attemptFakeRefresh(browser, expectRefresh) {
     26  await SpecialPowers.spawn(
     27    browser,
     28    [expectRefresh],
     29    async function (contentExpectRefresh) {
     30      let URI = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI;
     31      let refresher = docShell.QueryInterface(Ci.nsIRefreshURI);
     32      refresher.refreshURI(URI, null, 0);
     33 
     34      Assert.equal(
     35        refresher.refreshPending,
     36        contentExpectRefresh,
     37        "Got the right refreshPending state"
     38      );
     39 
     40      if (refresher.refreshPending) {
     41        // Cancel the pending refresh
     42        refresher.cancelRefreshURITimers();
     43      }
     44 
     45      // The RefreshBlocker will wait until onLocationChange has
     46      // been fired before it will show any notifications (see bug
     47      // 1246291), so we cause this to occur manually here.
     48      content.location = URI.spec + "#foo";
     49    }
     50  );
     51 }
     52 
     53 /**
     54 * Tests that we can enable the blocking pref and block a refresh
     55 * from occurring while showing a notification bar. Also tests that
     56 * when we disable the pref, that refreshes can go through again.
     57 */
     58 add_task(async function test_can_enable_and_block() {
     59  await BrowserTestUtils.withNewTab(
     60    {
     61      gBrowser,
     62      url: TARGET_PAGE,
     63    },
     64    async function (browser) {
     65      // By default, we should be able to reload the page.
     66      await attemptFakeRefresh(browser, true);
     67 
     68      await pushPrefs(["accessibility.blockautorefresh", true]);
     69 
     70      let notificationPromise = BrowserTestUtils.waitForNotificationBar(
     71        gBrowser,
     72        browser,
     73        "refresh-blocked"
     74      );
     75 
     76      await attemptFakeRefresh(browser, false);
     77 
     78      await notificationPromise;
     79 
     80      await pushPrefs(["accessibility.blockautorefresh", false]);
     81 
     82      // Page reloads should go through again.
     83      await attemptFakeRefresh(browser, true);
     84    }
     85  );
     86 });
     87 
     88 /**
     89 * Attempts a "real" refresh by opening a tab, and then sending it to
     90 * an SJS page that will attempt to cause a refresh. This will also pass
     91 * a delay amount to the SJS page. The refresh should be blocked, and
     92 * the notification should be shown. Once shown, the "Allow" button will
     93 * be clicked, and the refresh will go through. Finally, the helper will
     94 * close the tab and resolve the Promise.
     95 *
     96 * @param refreshPage (string)
     97 *        The SJS page to use. Use META_PAGE for the <meta> tag refresh
     98 *        case. Use HEADER_PAGE for the HTTP header case.
     99 * @param delay (int)
    100 *        The amount, in ms, for the page to wait before attempting the
    101 *        refresh.
    102 *
    103 * @returns Promise
    104 */
    105 async function testRealRefresh(refreshPage, delay) {
    106  await BrowserTestUtils.withNewTab(
    107    {
    108      gBrowser,
    109      url: "about:blank",
    110    },
    111    async function (browser) {
    112      await pushPrefs(["accessibility.blockautorefresh", true]);
    113 
    114      BrowserTestUtils.startLoadingURIString(
    115        browser,
    116        refreshPage + "?p=" + TARGET_PAGE + "&d=" + delay
    117      );
    118      await BrowserTestUtils.browserLoaded(browser);
    119 
    120      // Once browserLoaded resolves, all nsIWebProgressListener callbacks
    121      // should have fired, so the notification should be visible.
    122      let notificationBox = gBrowser.getNotificationBox(browser);
    123      let notification = notificationBox.currentNotification;
    124 
    125      ok(notification, "Notification should be visible");
    126      is(
    127        notification.getAttribute("value"),
    128        "refresh-blocked",
    129        "Should be showing the right notification"
    130      );
    131 
    132      // Then click the button to allow the refresh.
    133      let buttons = notification.buttonContainer.querySelectorAll(
    134        ".notification-button"
    135      );
    136      is(buttons.length, 1, "Should have one button.");
    137 
    138      // Prepare a Promise that should resolve when the refresh goes through
    139      let refreshPromise = BrowserTestUtils.browserLoaded(browser);
    140      buttons[0].click();
    141 
    142      await refreshPromise;
    143    }
    144  );
    145 }
    146 
    147 /**
    148 * Tests the meta-tag case for both short and longer delay times.
    149 */
    150 add_task(async function test_can_allow_refresh() {
    151  await testRealRefresh(META_PAGE, 0);
    152  await testRealRefresh(META_PAGE, 100);
    153  await testRealRefresh(META_PAGE, 500);
    154 });
    155 
    156 /**
    157 * Tests that when a HTTP header case for both short and longer
    158 * delay times.
    159 */
    160 add_task(async function test_can_block_refresh_from_header() {
    161  await testRealRefresh(HEADER_PAGE, 0);
    162  await testRealRefresh(HEADER_PAGE, 100);
    163  await testRealRefresh(HEADER_PAGE, 500);
    164 });
    165 
    166 /**
    167 * Tests that we can update a notification when multiple reload/redirect
    168 * attempts happen.
    169 */
    170 add_task(async function test_can_update_notification() {
    171  await BrowserTestUtils.withNewTab(
    172    {
    173      gBrowser,
    174      url: "about:blank",
    175    },
    176    async function (browser) {
    177      await pushPrefs(["accessibility.blockautorefresh", true]);
    178 
    179      // First, attempt a redirect
    180      BrowserTestUtils.startLoadingURIString(
    181        browser,
    182        META_PAGE + "?d=0&p=" + TARGET_PAGE
    183      );
    184      await BrowserTestUtils.browserLoaded(browser);
    185 
    186      // Once browserLoaded resolves, all nsIWebProgressListener callbacks
    187      // should have fired, so the notification should be visible.
    188      let notificationBox = gBrowser.getNotificationBox(browser);
    189      let notification = notificationBox.currentNotification;
    190      let [redirectLabel, refreshLabel] = await document.l10n.formatValues([
    191        { id: "refresh-blocked-redirect-label" },
    192        { id: "refresh-blocked-refresh-label" },
    193      ]);
    194 
    195      is(
    196        notification.messageText.textContent.trim(),
    197        redirectLabel,
    198        "Should be showing the redirect message"
    199      );
    200 
    201      // Next, attempt a refresh
    202      await attemptFakeRefresh(browser, false);
    203 
    204      is(
    205        notification.messageText.textContent.trim(),
    206        refreshLabel,
    207        "Should be showing the refresh message"
    208      );
    209    }
    210  );
    211 });