test-api.js (9216B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 /* globals Services */ 8 9 const { E10SUtils } = ChromeUtils.importESModule( 10 "resource://gre/modules/E10SUtils.sys.mjs" 11 ); 12 const { Preferences } = ChromeUtils.importESModule( 13 "resource://gre/modules/Preferences.sys.mjs" 14 ); 15 16 // eslint-disable-next-line mozilla/reject-importGlobalProperties 17 Cu.importGlobalProperties(["PathUtils"]); 18 19 this.test = class extends ExtensionAPI { 20 onStartup() { 21 ChromeUtils.registerWindowActor("TestSupport", { 22 child: { 23 esModuleURI: 24 "resource://android/assets/web_extensions/test-support/TestSupportChild.sys.mjs", 25 }, 26 allFrames: true, 27 }); 28 ChromeUtils.registerProcessActor("TestSupportProcess", { 29 child: { 30 esModuleURI: 31 "resource://android/assets/web_extensions/test-support/TestSupportProcessChild.sys.mjs", 32 }, 33 }); 34 } 35 36 onShutdown(isAppShutdown) { 37 if (isAppShutdown) { 38 return; 39 } 40 ChromeUtils.unregisterWindowActor("TestSupport"); 41 ChromeUtils.unregisterProcessActor("TestSupportProcess"); 42 } 43 44 getAPI(context) { 45 /** 46 * Helper function for getting window or process actors. 47 * 48 * @param tabId - id of the tab; required 49 * @param actorName - a string; the name of the actor 50 * Default: "TestSupport" which is our test framework actor 51 * (you can still pass the second parameter when getting the TestSupport actor, for readability) 52 * 53 * @returns actor 54 */ 55 function getActorForTab(tabId, actorName = "TestSupport") { 56 const tab = context.extension.tabManager.get(tabId); 57 const { browsingContext } = tab.browser; 58 return browsingContext.currentWindowGlobal.getActor(actorName); 59 } 60 61 return { 62 test: { 63 /* Set prefs and returns set of saved prefs */ 64 async setPrefs(oldPrefs, newPrefs) { 65 // Save old prefs 66 Object.assign( 67 oldPrefs, 68 ...Object.keys(newPrefs) 69 .filter(key => !(key in oldPrefs)) 70 .map(key => ({ [key]: Preferences.get(key, null) })) 71 ); 72 73 // Set new prefs 74 Preferences.set(newPrefs); 75 return oldPrefs; 76 }, 77 78 /* Restore prefs to old value. */ 79 async restorePrefs(oldPrefs) { 80 for (const [name, value] of Object.entries(oldPrefs)) { 81 if (value === null) { 82 Preferences.reset(name); 83 } else { 84 Preferences.set(name, value); 85 } 86 } 87 }, 88 89 /* Get pref values. */ 90 async getPrefs(prefs) { 91 return Preferences.get(prefs); 92 }, 93 94 /* Clears a given user preference. */ 95 async clearUserPref(pref) { 96 Services.prefs.clearUserPref(pref); 97 }, 98 /* Gets link color for a given selector. */ 99 async getLinkColor(tabId, selector) { 100 return getActorForTab(tabId, "TestSupport").sendQuery( 101 "GetLinkColor", 102 { selector } 103 ); 104 }, 105 106 async getRequestedLocales() { 107 return Services.locale.requestedLocales; 108 }, 109 110 async getPidForTab(tabId) { 111 const tab = context.extension.tabManager.get(tabId); 112 const pids = E10SUtils.getBrowserPids(tab.browser); 113 return pids[0]; 114 }, 115 116 async waitForContentTransformsReceived(tabId) { 117 return getActorForTab(tabId).sendQuery( 118 "WaitForContentTransformsReceived" 119 ); 120 }, 121 122 async getAllBrowserPids() { 123 const pids = []; 124 const processes = ChromeUtils.getAllDOMProcesses(); 125 for (const process of processes) { 126 if (process.remoteType && process.remoteType.startsWith("web")) { 127 pids.push(process.osPid); 128 } 129 } 130 return pids; 131 }, 132 133 async killContentProcess(pid) { 134 const procs = ChromeUtils.getAllDOMProcesses(); 135 for (const proc of procs) { 136 if (pid === proc.osPid) { 137 proc 138 .getActor("TestSupportProcess") 139 .sendAsyncMessage("KillContentProcess"); 140 } 141 } 142 }, 143 144 async addHistogram(id, value) { 145 return Services.telemetry.getHistogramById(id).add(value); 146 }, 147 148 removeAllCertOverrides() { 149 const overrideService = Cc[ 150 "@mozilla.org/security/certoverride;1" 151 ].getService(Ci.nsICertOverrideService); 152 overrideService.clearAllOverrides(); 153 }, 154 155 async setResolutionAndScaleTo(tabId, resolution) { 156 return getActorForTab(tabId, "TestSupport").sendQuery( 157 "SetResolutionAndScaleTo", 158 { 159 resolution, 160 } 161 ); 162 }, 163 164 async getActive(tabId) { 165 const tab = context.extension.tabManager.get(tabId); 166 return tab.browser.docShellIsActive; 167 }, 168 169 async getProfilePath() { 170 return PathUtils.profileDir; 171 }, 172 173 async flushApzRepaints(tabId) { 174 // TODO: Note that `waitUntilApzStable` in apz_test_utils.js does 175 // flush APZ repaints in the parent process (i.e. calling 176 // nsIDOMWindowUtils.flushApzRepaints for the parent process) before 177 // flushApzRepaints is called for the target content document, if we 178 // still meet intermittent failures, we might want to do it here as 179 // well. 180 await getActorForTab(tabId, "TestSupport").sendQuery( 181 "FlushApzRepaints" 182 ); 183 }, 184 185 async zoomToFocusedInput(tabId) { 186 await getActorForTab(tabId, "TestSupport").sendQuery( 187 "ZoomToFocusedInput" 188 ); 189 }, 190 191 async promiseAllPaintsDone(tabId) { 192 await getActorForTab(tabId, "TestSupport").sendQuery( 193 "PromiseAllPaintsDone" 194 ); 195 }, 196 197 async usingGpuProcess() { 198 const gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService( 199 Ci.nsIGfxInfo 200 ); 201 return gfxInfo.usingGPUProcess; 202 }, 203 204 async killGpuProcess() { 205 const gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService( 206 Ci.nsIGfxInfo 207 ); 208 return gfxInfo.killGPUProcessForTests(); 209 }, 210 211 async crashGpuProcess() { 212 const gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService( 213 Ci.nsIGfxInfo 214 ); 215 return gfxInfo.crashGPUProcessForTests(); 216 }, 217 218 async clearHSTSState() { 219 const sss = Cc["@mozilla.org/ssservice;1"].getService( 220 Ci.nsISiteSecurityService 221 ); 222 return sss.clearAll(); 223 }, 224 225 async isSessionHistoryInParentRunning() { 226 return Services.appinfo.sessionHistoryInParent; 227 }, 228 229 async isFissionRunning() { 230 return Services.appinfo.fissionAutostart; 231 }, 232 233 async triggerCookieBannerDetected(tabId) { 234 const actor = getActorForTab(tabId, "CookieBanner"); 235 return actor.receiveMessage({ 236 name: "CookieBanner::DetectedBanner", 237 }); 238 }, 239 240 async triggerCookieBannerHandled(tabId) { 241 const actor = getActorForTab(tabId, "CookieBanner"); 242 return actor.receiveMessage({ 243 name: "CookieBanner::HandledBanner", 244 }); 245 }, 246 247 async triggerTranslationsOffer(tabId) { 248 const browser = context.extension.tabManager.get(tabId).browser; 249 const { CustomEvent } = browser.ownerGlobal; 250 return browser.dispatchEvent( 251 new CustomEvent("TranslationsParent:OfferTranslation", { 252 bubbles: true, 253 }) 254 ); 255 }, 256 257 async triggerLanguageStateChange(tabId, languageState) { 258 const browser = context.extension.tabManager.get(tabId).browser; 259 const { CustomEvent } = browser.ownerGlobal; 260 return browser.dispatchEvent( 261 new CustomEvent("TranslationsParent:LanguageState", { 262 bubbles: true, 263 detail: languageState, 264 }) 265 ); 266 }, 267 268 async setHandlingUserInput(tabId, handlingUserInput) { 269 return getActorForTab(tabId, "TestSupport").sendQuery( 270 "SetHandlingUserInput", 271 { handlingUserInput } 272 ); 273 }, 274 275 async getWebExtensionsSchemaPermissionNames(typeNames) { 276 const { Schemas } = ChromeUtils.importESModule( 277 "resource://gre/modules/Schemas.sys.mjs" 278 ); 279 return Schemas.getPermissionNames(typeNames); 280 }, 281 282 async teardownAlertsService() { 283 const alertsService = Cc["@mozilla.org/alerts-service;1"].getService( 284 Ci.nsIAlertsService 285 ); 286 alertsService.teardown(); 287 }, 288 289 async notifyUserGestureActivation(tabId) { 290 return getActorForTab(tabId, "TestSupport").sendQuery( 291 "NotifyUserGestureActivation" 292 ); 293 }, 294 }, 295 }; 296 } 297 };