browser_interventions.js (7784B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 ChromeUtils.defineESModuleGetters(this, { 7 UrlbarProviderInterventions: 8 "moz-src:///browser/components/urlbar/UrlbarProviderInterventions.sys.mjs", 9 }); 10 11 add_setup(async function () { 12 Services.telemetry.clearEvents(); 13 makeProfileResettable(); 14 15 await SpecialPowers.pushPrefEnv({ 16 set: [["browser.urlbar.scotchBonnet.enableOverride", false]], 17 }); 18 }); 19 20 // Tests the refresh tip. 21 add_task(async function refresh() { 22 // Pick the tip, which should open the refresh dialog. Click its cancel 23 // button. 24 await checkIntervention({ 25 searchString: SEARCH_STRINGS.REFRESH, 26 tip: UrlbarProviderInterventions.TIP_TYPE.REFRESH, 27 title: 28 "Restore default settings and remove old add-ons for optimal performance.", 29 button: /^Refresh .+…$/, 30 awaitCallback() { 31 return BrowserTestUtils.promiseAlertDialog( 32 "cancel", 33 "chrome://global/content/resetProfile.xhtml", 34 { isSubDialog: true } 35 ); 36 }, 37 }); 38 }); 39 40 // Tests the clear tip. 41 add_task(async function clear() { 42 // Pick the tip, which should open the refresh dialog. Click its cancel 43 // button. 44 let useOldClearHistoryDialog = Services.prefs.getBoolPref( 45 "privacy.sanitize.useOldClearHistoryDialog" 46 ); 47 let dialogURL = useOldClearHistoryDialog 48 ? "chrome://browser/content/sanitize.xhtml" 49 : "chrome://browser/content/sanitize_v2.xhtml"; 50 await checkIntervention({ 51 searchString: SEARCH_STRINGS.CLEAR, 52 tip: UrlbarProviderInterventions.TIP_TYPE.CLEAR, 53 title: "Clear your cache, cookies, history and more.", 54 button: "Choose What to Clear…", 55 awaitCallback() { 56 return BrowserTestUtils.promiseAlertDialog("cancel", dialogURL, { 57 isSubDialog: true, 58 }); 59 }, 60 }); 61 }); 62 63 // Tests the clear tip in a private window. The clear tip shouldn't appear in 64 // private windows. 65 add_task(async function clear_private() { 66 let win = await BrowserTestUtils.openNewBrowserWindow({ private: true }); 67 // First, make sure the extension works in PBM by triggering a non-clear 68 // tip. 69 let result = (await awaitTip(SEARCH_STRINGS.REFRESH, win))[0]; 70 Assert.strictEqual( 71 result.payload.type, 72 UrlbarProviderInterventions.TIP_TYPE.REFRESH 73 ); 74 75 // Blur the urlbar so that the engagement is ended. 76 await UrlbarTestUtils.promisePopupClose(win, () => win.gURLBar.blur()); 77 78 // Now do a search that would trigger the clear tip. 79 await awaitNoTip(SEARCH_STRINGS.CLEAR, win); 80 81 // Blur the urlbar so that the engagement is ended. 82 await UrlbarTestUtils.promisePopupClose(win, () => win.gURLBar.blur()); 83 84 await BrowserTestUtils.closeWindow(win); 85 }); 86 87 // Test the result of UrlbarProviderInterventions.isActive() 88 // and whether or not the function calucates the score. 89 add_task(async function testIsActive() { 90 const testData = [ 91 { 92 description: "Test for search string that activates the intervention", 93 searchString: "firefox slow", 94 expectedActive: true, 95 expectedScoreCalculated: true, 96 }, 97 { 98 description: 99 "Test for search string that does not activate the intervention", 100 searchString: "example slow", 101 expectedActive: false, 102 expectedScoreCalculated: true, 103 }, 104 { 105 description: "Test for empty search string", 106 searchString: "", 107 expectedActive: false, 108 expectedScoreCalculated: false, 109 }, 110 { 111 description: "Test for an URL", 112 searchString: "https://firefox/slow", 113 expectedActive: false, 114 expectedScoreCalculated: false, 115 }, 116 { 117 description: "Test for a data URL", 118 searchString: "data:text/html,<div>firefox slow</div>", 119 expectedActive: false, 120 expectedScoreCalculated: false, 121 }, 122 { 123 description: "Test for string like URL", 124 searchString: "firefox://slow", 125 expectedActive: false, 126 expectedScoreCalculated: false, 127 }, 128 ]; 129 130 let interventionsProviderInstance = UrlbarProvidersManager.getProvider( 131 "UrlbarProviderInterventions" 132 ); 133 // Mock the relevent method of Query so we don't have to start a real one. 134 interventionsProviderInstance.queryInstance = { 135 getProvider: name => UrlbarProvidersManager.getProvider(name), 136 }; 137 for (const { 138 description, 139 searchString, 140 expectedActive, 141 expectedScoreCalculated, 142 } of testData) { 143 info(description); 144 145 // Set null to currentTip to know whether or not UrlbarProviderInterventions 146 // calculated the score. 147 interventionsProviderInstance.currentTip = null; 148 149 const isActive = await interventionsProviderInstance.isActive({ 150 searchString, 151 }); 152 Assert.equal(isActive, expectedActive, "Result of isActive is correct"); 153 const isScoreCalculated = interventionsProviderInstance.currentTip !== null; 154 Assert.equal( 155 isScoreCalculated, 156 expectedScoreCalculated, 157 "The score is calculated correctly" 158 ); 159 } 160 interventionsProviderInstance.queryInstance = null; 161 }); 162 163 add_task(async function tipsAreEnglishOnly() { 164 // Test that Interventions are working in en-US. 165 let result = (await awaitTip(SEARCH_STRINGS.REFRESH, window))[0]; 166 Assert.strictEqual( 167 result.payload.type, 168 UrlbarProviderInterventions.TIP_TYPE.REFRESH 169 ); 170 await UrlbarTestUtils.promisePopupClose(window, () => gURLBar.blur()); 171 172 // We will need to fetch new engines when we switch locales. 173 let enginesReloaded = 174 SearchTestUtils.promiseSearchNotification("engines-reloaded"); 175 176 const originalAvailable = Services.locale.availableLocales; 177 const originalRequested = Services.locale.requestedLocales; 178 Services.locale.availableLocales = ["en-US", "de"]; 179 Services.locale.requestedLocales = ["de"]; 180 181 let cleanup = async () => { 182 let reloadPromise = 183 SearchTestUtils.promiseSearchNotification("engines-reloaded"); 184 Services.locale.requestedLocales = originalRequested; 185 Services.locale.availableLocales = originalAvailable; 186 await reloadPromise; 187 cleanup = null; 188 }; 189 registerCleanupFunction(() => cleanup?.()); 190 191 let appLocales = Services.locale.appLocalesAsBCP47; 192 Assert.equal(appLocales[0], "de"); 193 194 await enginesReloaded; 195 196 // Interventions should no longer work in the new locale. 197 await awaitNoTip(SEARCH_STRINGS.CLEAR, window); 198 await UrlbarTestUtils.promisePopupClose(window, () => gURLBar.blur()); 199 200 await cleanup(); 201 }); 202 203 // Tests the help command (using the clear intervention). It should open the 204 // help page and it should not trigger the primary intervention behavior. 205 add_task(async function pickHelp() { 206 await BrowserTestUtils.withNewTab("about:blank", async () => { 207 // Do a search that triggers the clear tip. 208 let [result] = await awaitTip(SEARCH_STRINGS.CLEAR); 209 Assert.strictEqual( 210 result.payload.type, 211 UrlbarProviderInterventions.TIP_TYPE.CLEAR 212 ); 213 214 // Click the help command and wait for the help page to load. 215 Assert.ok( 216 !!result.payload.helpUrl, 217 "The result's helpUrl should be defined and non-empty: " + 218 JSON.stringify(result.payload.helpUrl) 219 ); 220 let newTabOpened = BrowserTestUtils.waitForNewTab( 221 gBrowser, 222 result.payload.helpUrl 223 ); 224 await UrlbarTestUtils.openResultMenuAndPressAccesskey(window, "h", { 225 openByMouse: true, 226 resultIndex: 1, 227 }); 228 info("Waiting for help URL to load in the current tab"); 229 let newTab = await newTabOpened; 230 await BrowserTestUtils.removeTab(newTab); 231 232 // Wait a bit and make sure the clear recent history dialog did not open. 233 // eslint-disable-next-line mozilla/no-arbitrary-setTimeout 234 await new Promise(r => setTimeout(r, 2000)); 235 Assert.strictEqual(gDialogBox.isOpen, false, "No dialog should be open"); 236 }); 237 });