tor-browser

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

head.js (7572B)


      1 ChromeUtils.defineESModuleGetters(this, {
      2  AboutNewTab: "resource:///modules/AboutNewTab.sys.mjs",
      3  PlacesTestUtils: "resource://testing-common/PlacesTestUtils.sys.mjs",
      4  PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
      5  TabCrashHandler: "resource:///modules/ContentCrashHandlers.sys.mjs",
      6 });
      7 
      8 /**
      9 * Wait for a <notification> to be closed then call the specified callback.
     10 */
     11 function waitForNotificationClose(notification, cb) {
     12  let observer = new MutationObserver(function onMutatations(mutations) {
     13    for (let mutation of mutations) {
     14      for (let i = 0; i < mutation.removedNodes.length; i++) {
     15        let node = mutation.removedNodes.item(i);
     16        if (node != notification) {
     17          continue;
     18        }
     19        observer.disconnect();
     20        cb();
     21      }
     22    }
     23  });
     24  observer.observe(notification.control.stack, { childList: true });
     25 }
     26 
     27 function closeAllNotifications() {
     28  if (!gNotificationBox.currentNotification) {
     29    return Promise.resolve();
     30  }
     31 
     32  return new Promise(resolve => {
     33    for (let notification of gNotificationBox.allNotifications) {
     34      waitForNotificationClose(notification, function () {
     35        if (gNotificationBox.allNotifications.length === 0) {
     36          resolve();
     37        }
     38      });
     39      notification.close();
     40    }
     41  });
     42 }
     43 
     44 function whenDelayedStartupFinished(aWindow, aCallback) {
     45  Services.obs.addObserver(function observer(aSubject, aTopic) {
     46    if (aWindow == aSubject) {
     47      Services.obs.removeObserver(observer, aTopic);
     48      executeSoon(aCallback);
     49    }
     50  }, "browser-delayed-startup-finished");
     51 }
     52 
     53 function openToolbarCustomizationUI(aCallback, aBrowserWin) {
     54  if (!aBrowserWin) {
     55    aBrowserWin = window;
     56  }
     57 
     58  aBrowserWin.gCustomizeMode.enter();
     59 
     60  aBrowserWin.gNavToolbox.addEventListener(
     61    "customizationready",
     62    function () {
     63      executeSoon(function () {
     64        aCallback(aBrowserWin);
     65      });
     66    },
     67    { once: true }
     68  );
     69 }
     70 
     71 function closeToolbarCustomizationUI(aCallback, aBrowserWin) {
     72  aBrowserWin.gNavToolbox.addEventListener(
     73    "aftercustomization",
     74    function () {
     75      executeSoon(aCallback);
     76    },
     77    { once: true }
     78  );
     79 
     80  aBrowserWin.gCustomizeMode.exit();
     81 }
     82 
     83 function waitForCondition(condition, nextTest, errorMsg, retryTimes) {
     84  retryTimes = typeof retryTimes !== "undefined" ? retryTimes : 30;
     85  var tries = 0;
     86  var interval = setInterval(function () {
     87    if (tries >= retryTimes) {
     88      ok(false, errorMsg);
     89      moveOn();
     90    }
     91    var conditionPassed;
     92    try {
     93      conditionPassed = condition();
     94    } catch (e) {
     95      ok(false, e + "\n" + e.stack);
     96      conditionPassed = false;
     97    }
     98    if (conditionPassed) {
     99      moveOn();
    100    }
    101    tries++;
    102  }, 100);
    103  var moveOn = function () {
    104    clearInterval(interval);
    105    nextTest();
    106  };
    107 }
    108 
    109 function promiseWaitForCondition(aConditionFn) {
    110  return new Promise(resolve => {
    111    waitForCondition(aConditionFn, resolve, "Condition didn't pass.");
    112  });
    113 }
    114 
    115 function promiseWaitForEvent(
    116  object,
    117  eventName,
    118  capturing = false,
    119  chrome = false
    120 ) {
    121  return new Promise(resolve => {
    122    function listener(event) {
    123      info("Saw " + eventName);
    124      object.removeEventListener(eventName, listener, capturing, chrome);
    125      resolve(event);
    126    }
    127 
    128    info("Waiting for " + eventName);
    129    object.addEventListener(eventName, listener, capturing, chrome);
    130  });
    131 }
    132 
    133 /**
    134 * Allows setting focus on a window, and waiting for that window to achieve
    135 * focus.
    136 *
    137 * @param aWindow
    138 *        The window to focus and wait for.
    139 *
    140 * @returns {Promise<void>}
    141 *   Resolved when the window is focused.
    142 */
    143 function promiseWaitForFocus(aWindow) {
    144  return new Promise(resolve => {
    145    waitForFocus(resolve, aWindow);
    146  });
    147 }
    148 
    149 function pushPrefs(...aPrefs) {
    150  return SpecialPowers.pushPrefEnv({ set: aPrefs });
    151 }
    152 
    153 function popPrefs() {
    154  return SpecialPowers.popPrefEnv();
    155 }
    156 
    157 function promiseWindowClosed(win) {
    158  let promise = BrowserTestUtils.domWindowClosed(win);
    159  win.close();
    160  return promise;
    161 }
    162 
    163 async function whenNewTabLoaded(aWindow, aCallback) {
    164  aWindow.BrowserCommands.openTab();
    165 
    166  let expectedURL = AboutNewTab.newTabURL;
    167  let browser = aWindow.gBrowser.selectedBrowser;
    168  let loadPromise = BrowserTestUtils.browserLoaded(browser, false, expectedURL);
    169  let alreadyLoaded = await SpecialPowers.spawn(browser, [expectedURL], url => {
    170    let doc = content.document;
    171    return doc && doc.readyState === "complete" && doc.location.href == url;
    172  });
    173  if (!alreadyLoaded) {
    174    await loadPromise;
    175  }
    176  aCallback();
    177 }
    178 
    179 function is_hidden(element) {
    180  var style = element.ownerGlobal.getComputedStyle(element);
    181  if (style.display == "none") {
    182    return true;
    183  }
    184  if (style.visibility != "visible") {
    185    return true;
    186  }
    187  if (XULPopupElement.isInstance(element)) {
    188    return ["hiding", "closed"].includes(element.state);
    189  }
    190 
    191  // Hiding a parent element will hide all its children
    192  if (element.parentNode != element.ownerDocument) {
    193    return is_hidden(element.parentNode);
    194  }
    195 
    196  return false;
    197 }
    198 
    199 function is_element_visible(element, msg) {
    200  isnot(element, null, "Element should not be null, when checking visibility");
    201  ok(BrowserTestUtils.isVisible(element), msg || "Element should be visible");
    202 }
    203 
    204 function is_element_hidden(element, msg) {
    205  isnot(element, null, "Element should not be null, when checking visibility");
    206  ok(is_hidden(element), msg || "Element should be hidden");
    207 }
    208 
    209 function promisePopupShown(popup) {
    210  return BrowserTestUtils.waitForPopupEvent(popup, "shown");
    211 }
    212 
    213 function promisePopupHidden(popup) {
    214  return BrowserTestUtils.waitForPopupEvent(popup, "hidden");
    215 }
    216 
    217 function promiseNotificationShown(notification) {
    218  let win = notification.browser.ownerGlobal;
    219  if (win.PopupNotifications.panel.state == "open") {
    220    return Promise.resolve();
    221  }
    222  let panelPromise = promisePopupShown(win.PopupNotifications.panel);
    223  notification.reshow();
    224  return panelPromise;
    225 }
    226 
    227 /**
    228 * Resolves when a bookmark with the given uri is added.
    229 */
    230 function promiseOnBookmarkItemAdded(aExpectedURI) {
    231  return new Promise((resolve, reject) => {
    232    let listener = events => {
    233      is(events.length, 1, "Should only receive one event.");
    234      info("Added a bookmark to " + events[0].url);
    235      PlacesUtils.observers.removeListener(["bookmark-added"], listener);
    236      if (events[0].url == aExpectedURI.spec) {
    237        resolve();
    238      } else {
    239        reject(new Error("Added an unexpected bookmark"));
    240      }
    241    };
    242    info("Waiting for a bookmark to be added");
    243    PlacesUtils.observers.addListener(["bookmark-added"], listener);
    244  });
    245 }
    246 
    247 async function loadBadCertPage(url, feltPrivacy = false) {
    248  let loaded = BrowserTestUtils.waitForErrorPage(gBrowser.selectedBrowser);
    249  BrowserTestUtils.startLoadingURIString(gBrowser.selectedBrowser, url);
    250  await loaded;
    251 
    252  await SpecialPowers.spawn(
    253    gBrowser.selectedBrowser,
    254    [feltPrivacy],
    255    async isFeltPrivacy => {
    256      if (isFeltPrivacy) {
    257        let netErrorCard =
    258          content.document.querySelector("net-error-card").wrappedJSObject;
    259        await netErrorCard.getUpdateComplete();
    260        netErrorCard.advancedButton.click();
    261        await ContentTaskUtils.waitForCondition(() => {
    262          return (
    263            netErrorCard.exceptionButton &&
    264            !netErrorCard.exceptionButton.disabled
    265          );
    266        }, "Waiting for exception button");
    267        netErrorCard.exceptionButton.click();
    268      } else {
    269        content.document.getElementById("exceptionDialogButton").click();
    270      }
    271    }
    272  );
    273  await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
    274 }