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 });