tor-browser

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

browser_basic_rebuild_fonts_test.js (7734B)


      1 add_task(async function () {
      2  await openPreferencesViaOpenPreferencesAPI("general", { leaveOpen: true });
      3  await gBrowser.contentWindow.gMainPane._selectDefaultLanguageGroupPromise;
      4  await TestUtils.waitForCondition(
      5    () => !gBrowser.contentWindow.Preferences.updateQueued
      6  );
      7 
      8  let doc = gBrowser.contentDocument;
      9  let contentWindow = gBrowser.contentWindow;
     10  let langGroup = Services.locale.fontLanguageGroup;
     11  let defaultFontType = Services.prefs.getCharPref("font.default." + langGroup);
     12  let fontFamilyPref = "font.name." + defaultFontType + "." + langGroup;
     13  let fontFamily = Services.prefs.getCharPref(fontFamilyPref);
     14  let fontFamilyField = doc.getElementById("defaultFont");
     15  is(fontFamilyField.value, fontFamily, "Font family should be set correctly.");
     16  is(
     17    fontFamilyField.getAttribute("preference"),
     18    fontFamilyPref,
     19    "langGroup is used in defaultFont preference"
     20  );
     21 
     22  function dispatchMenuItemCommand(menuItem) {
     23    const cmdEvent = doc.createEvent("xulcommandevent");
     24    cmdEvent.initCommandEvent(
     25      "command",
     26      true,
     27      true,
     28      contentWindow,
     29      0,
     30      false,
     31      false,
     32      false,
     33      false,
     34      0,
     35      null,
     36      0
     37    );
     38    menuItem.dispatchEvent(cmdEvent);
     39  }
     40 
     41  /**
     42   * Return a promise that resolves when the fontFamilyPref changes.
     43   *
     44   * Font prefs are the only ones whose form controls set "delayprefsave",
     45   * which delays the pref change when a user specifies a new value
     46   * for the pref.  Thus, in order to confirm that the pref gets changed
     47   * when the test selects a new value in a font field, we need to await
     48   * the change.  Awaiting this function does so for fontFamilyPref.
     49   */
     50  function fontFamilyPrefChanged() {
     51    return new Promise(resolve => {
     52      const observer = {
     53        observe(aSubject, aTopic, aData) {
     54          // Check for an exact match to avoid the ambiguity of nsIPrefBranch's
     55          // prefix-matching algorithm for notifying pref observers.
     56          if (aData == fontFamilyPref) {
     57            Services.prefs.removeObserver(fontFamilyPref, observer);
     58            resolve();
     59          }
     60        },
     61      };
     62      Services.prefs.addObserver(fontFamilyPref, observer);
     63    });
     64  }
     65 
     66  const menuItems = fontFamilyField.querySelectorAll("menuitem");
     67  Assert.greater(menuItems.length, 1, "There are multiple font menuitems.");
     68  ok(menuItems[0].selected, "The first (default) font menuitem is selected.");
     69 
     70  dispatchMenuItemCommand(menuItems[1]);
     71  ok(menuItems[1].selected, "The second font menuitem is selected.");
     72 
     73  await fontFamilyPrefChanged();
     74  fontFamily = Services.prefs.getCharPref(fontFamilyPref);
     75  is(fontFamilyField.value, fontFamily, "The font family has been updated.");
     76 
     77  dispatchMenuItemCommand(menuItems[0]);
     78  ok(
     79    menuItems[0].selected,
     80    "The first (default) font menuitem is selected again."
     81  );
     82 
     83  await fontFamilyPrefChanged();
     84  fontFamily = Services.prefs.getCharPref(fontFamilyPref);
     85  is(fontFamilyField.value, fontFamily, "The font family has been updated.");
     86 
     87  let defaultFontSize = Services.prefs.getIntPref(
     88    "font.size.variable." + langGroup
     89  );
     90  let fontSizeField = doc.getElementById("defaultFontSize");
     91  is(
     92    fontSizeField.value,
     93    "" + defaultFontSize,
     94    "Font size should be set correctly."
     95  );
     96 
     97  let promiseSubDialogLoaded = promiseLoadSubDialog(
     98    "chrome://browser/content/preferences/dialogs/fonts.xhtml"
     99  );
    100  doc.getElementById("advancedFonts").click();
    101  let win = await promiseSubDialogLoaded;
    102  doc = win.document;
    103 
    104  // Simulate a dumb font backend.
    105  win.FontBuilder._enumerator = {
    106    _list: ["MockedFont1", "MockedFont2", "MockedFont3"],
    107    _defaultFont: null,
    108    EnumerateFontsAsync() {
    109      return Promise.resolve(this._list);
    110    },
    111    EnumerateAllFontsAsync() {
    112      return Promise.resolve(this._list);
    113    },
    114    getDefaultFont() {
    115      return this._defaultFont;
    116    },
    117    getStandardFamilyName(name) {
    118      return name;
    119    },
    120  };
    121  win.FontBuilder._allFonts = null;
    122  win.FontBuilder._langGroupSupported = false;
    123 
    124  let langGroupElement = win.Preferences.get("font.language.group");
    125  let selectLangsField = doc.getElementById("selectLangs");
    126  let serifField = doc.getElementById("serif");
    127  let armenian = "x-armn";
    128  let western = "x-western";
    129 
    130  // Await rebuilding of the font lists, which happens asynchronously in
    131  // gFontsDialog._selectLanguageGroup.  Testing code needs to call this
    132  // function and await its resolution after changing langGroupElement's value
    133  // (or doing anything else that triggers a call to _selectLanguageGroup).
    134  function fontListsRebuilt() {
    135    return win.gFontsDialog._selectLanguageGroupPromise;
    136  }
    137 
    138  langGroupElement.value = armenian;
    139  await fontListsRebuilt();
    140  selectLangsField.value = armenian;
    141  is(serifField.value, "", "Font family should not be set.");
    142 
    143  let armenianSerifElement = win.Preferences.get("font.name.serif.x-armn");
    144 
    145  langGroupElement.value = western;
    146  await fontListsRebuilt();
    147  selectLangsField.value = western;
    148 
    149  // Simulate a font backend supporting language-specific enumeration.
    150  // NB: FontBuilder has cached the return value from EnumerateAllFonts(),
    151  // so _allFonts will always have 3 elements regardless of subsequent
    152  // _list changes.
    153  win.FontBuilder._enumerator._list = ["MockedFont2"];
    154 
    155  langGroupElement.value = armenian;
    156  await fontListsRebuilt();
    157  selectLangsField.value = armenian;
    158  is(
    159    serifField.value,
    160    "",
    161    "Font family should still be empty for indicating using 'default' font."
    162  );
    163 
    164  langGroupElement.value = western;
    165  await fontListsRebuilt();
    166  selectLangsField.value = western;
    167 
    168  // Simulate a system that has no fonts for the specified language.
    169  win.FontBuilder._enumerator._list = [];
    170 
    171  langGroupElement.value = armenian;
    172  await fontListsRebuilt();
    173  selectLangsField.value = armenian;
    174  is(serifField.value, "", "Font family should not be set.");
    175 
    176  // Setting default font to "MockedFont3".  Then, when serifField.value is
    177  // empty, it should indicate using "MockedFont3" but it shouldn't be saved
    178  // to "MockedFont3" in the pref.  It should be resolved at runtime.
    179  win.FontBuilder._enumerator._list = [
    180    "MockedFont1",
    181    "MockedFont2",
    182    "MockedFont3",
    183  ];
    184  win.FontBuilder._enumerator._defaultFont = "MockedFont3";
    185  langGroupElement.value = armenian;
    186  await fontListsRebuilt();
    187  selectLangsField.value = armenian;
    188  is(
    189    serifField.value,
    190    "",
    191    "Font family should be empty even if there is a default font."
    192  );
    193 
    194  armenianSerifElement.value = "MockedFont2";
    195  serifField.value = "MockedFont2";
    196  is(
    197    serifField.value,
    198    "MockedFont2",
    199    'Font family should be "MockedFont2" for now.'
    200  );
    201 
    202  langGroupElement.value = western;
    203  await fontListsRebuilt();
    204  selectLangsField.value = western;
    205  is(serifField.value, "", "Font family of other language should not be set.");
    206 
    207  langGroupElement.value = armenian;
    208  await fontListsRebuilt();
    209  selectLangsField.value = armenian;
    210  is(
    211    serifField.value,
    212    "MockedFont2",
    213    "Font family should not be changed even after switching the language."
    214  );
    215 
    216  // If MochedFont2 is removed from the system, the value should be treated
    217  // as empty (i.e., 'default' font) after rebuilding the font list.
    218  win.FontBuilder._enumerator._list = ["MockedFont1", "MockedFont3"];
    219  win.FontBuilder._enumerator._allFonts = ["MockedFont1", "MockedFont3"];
    220  serifField.removeAllItems(); // This will cause rebuilding the font list from available fonts.
    221  langGroupElement.value = armenian;
    222  await fontListsRebuilt();
    223  selectLangsField.value = armenian;
    224  is(
    225    serifField.value,
    226    "",
    227    "Font family should become empty due to the font uninstalled."
    228  );
    229 
    230  gBrowser.removeCurrentTab();
    231 });