client-wrapper.js (6262B)
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 const { 8 checkVersionCompatibility, 9 } = require("resource://devtools/client/shared/remote-debugging/version-checker.js"); 10 11 const { 12 RUNTIME_PREFERENCE, 13 } = require("resource://devtools/client/aboutdebugging/src/constants.js"); 14 const { 15 WorkersListener, 16 } = require("resource://devtools/client/shared/workers-listener.js"); 17 const RootResourceCommand = require("resource://devtools/shared/commands/root-resource/root-resource-command.js"); 18 19 const PREF_TYPES = { 20 BOOL: "BOOL", 21 }; 22 23 // Map of preference to preference type. 24 const PREF_TO_TYPE = { 25 [RUNTIME_PREFERENCE.CHROME_DEBUG_ENABLED]: PREF_TYPES.BOOL, 26 [RUNTIME_PREFERENCE.CONNECTION_PROMPT]: PREF_TYPES.BOOL, 27 [RUNTIME_PREFERENCE.PERMANENT_PRIVATE_BROWSING]: PREF_TYPES.BOOL, 28 [RUNTIME_PREFERENCE.REMOTE_DEBUG_ENABLED]: PREF_TYPES.BOOL, 29 [RUNTIME_PREFERENCE.SERVICE_WORKERS_ENABLED]: PREF_TYPES.BOOL, 30 }; 31 32 // Some events are fired by mainRoot rather than client. 33 const MAIN_ROOT_EVENTS = ["addonListChanged", "tabListChanged"]; 34 35 /** 36 * The ClientWrapper class is used to isolate aboutdebugging from the DevTools client API 37 * The modules of about:debugging should never call DevTools client APIs directly. 38 */ 39 class ClientWrapper { 40 constructor(client) { 41 this.client = client; 42 this.workersListener = new WorkersListener(client.mainRoot); 43 } 44 45 once(evt, listener) { 46 if (MAIN_ROOT_EVENTS.includes(evt)) { 47 this.client.mainRoot.once(evt, listener); 48 } else { 49 this.client.once(evt, listener); 50 } 51 } 52 53 on(evt, listener) { 54 if (evt === "workersUpdated") { 55 this.workersListener.addListener(listener); 56 } else if (MAIN_ROOT_EVENTS.includes(evt)) { 57 this.client.mainRoot.on(evt, listener); 58 } else { 59 this.client.on(evt, listener); 60 } 61 } 62 63 off(evt, listener) { 64 if (evt === "workersUpdated") { 65 this.workersListener.removeListener(listener); 66 } else if (MAIN_ROOT_EVENTS.includes(evt)) { 67 this.client.mainRoot.off(evt, listener); 68 } else { 69 this.client.off(evt, listener); 70 } 71 } 72 73 async getFront(typeName) { 74 return this.client.mainRoot.getFront(typeName); 75 } 76 77 async getDeviceDescription() { 78 const deviceFront = await this.getFront("device"); 79 const description = await deviceFront.getDescription(); 80 81 // Only expose a specific set of properties. 82 return { 83 canDebugServiceWorkers: description.canDebugServiceWorkers, 84 channel: description.channel, 85 deviceName: description.deviceName, 86 name: description.brandName, 87 os: description.os, 88 version: description.version, 89 }; 90 } 91 92 createRootResourceCommand() { 93 return new RootResourceCommand({ rootFront: this.client.mainRoot }); 94 } 95 96 async checkVersionCompatibility() { 97 return checkVersionCompatibility(this.client); 98 } 99 100 async setPreference(prefName, value) { 101 const prefType = PREF_TO_TYPE[prefName]; 102 const preferenceFront = await this.client.mainRoot.getFront("preference"); 103 switch (prefType) { 104 case PREF_TYPES.BOOL: 105 return preferenceFront.setBoolPref(prefName, value); 106 default: 107 throw new Error("Unsupported preference" + prefName); 108 } 109 } 110 111 async getPreference(prefName, defaultValue) { 112 if (typeof defaultValue === "undefined") { 113 throw new Error( 114 "Default value is mandatory for getPreference, the actor will " + 115 "throw if the preference is not set on the target runtime" 116 ); 117 } 118 119 const prefType = PREF_TO_TYPE[prefName]; 120 const preferenceFront = await this.client.mainRoot.getFront("preference"); 121 switch (prefType) { 122 case PREF_TYPES.BOOL: { 123 // TODO: Add server-side trait and methods to pass a default value to getBoolPref. 124 // See Bug 1522588. 125 let prefValue; 126 try { 127 prefValue = await preferenceFront.getBoolPref(prefName); 128 } catch (e) { 129 prefValue = defaultValue; 130 } 131 return prefValue; 132 } 133 default: 134 throw new Error("Unsupported preference:" + prefName); 135 } 136 } 137 138 async listTabs() { 139 return this.client.mainRoot.listTabs(); 140 } 141 142 async listAddons(options) { 143 return this.client.mainRoot.listAddons(options); 144 } 145 146 async getAddon({ id }) { 147 return this.client.mainRoot.getAddon({ id }); 148 } 149 150 async uninstallAddon({ id }) { 151 const addonsFront = await this.getFront("addons"); 152 return addonsFront.uninstallAddon(id); 153 } 154 155 async getMainProcess() { 156 return this.client.mainRoot.getMainProcess(); 157 } 158 159 async getServiceWorkerFront({ id }) { 160 return this.client.mainRoot.getWorker(id); 161 } 162 163 async listWorkers() { 164 const { other, service, shared } = 165 await this.client.mainRoot.listAllWorkers(); 166 167 return { 168 otherWorkers: other, 169 serviceWorkers: service, 170 sharedWorkers: shared, 171 }; 172 } 173 174 async close() { 175 return this.client.close(); 176 } 177 178 isClosed() { 179 return this.client._transportClosed; 180 } 181 182 // This method will be mocked to return a dummy URL during mochitests 183 getPerformancePanelUrl() { 184 return "chrome://devtools/content/performance-new/panel/index.xhtml"; 185 } 186 187 /** 188 * @param {Window} win - The window of the dialog window. 189 * @param {Function} openAboutProfiling 190 */ 191 async loadPerformanceProfiler(win, openAboutProfiling) { 192 const perfFront = await this.getFront("perf"); 193 const { traits } = this.client; 194 await win.gInit(perfFront, traits, "devtools-remote", openAboutProfiling); 195 } 196 197 /** 198 * @param {Window} win - The window of the dialog window. 199 * @param {Function} openRemoteDevTools 200 */ 201 async loadAboutProfiling(win, openRemoteDevTools) { 202 const perfFront = await this.getFront("perf"); 203 const isSupportedPlatform = await perfFront.isSupportedPlatform(); 204 const supportedFeatures = await perfFront.getSupportedFeatures(); 205 await win.gInit( 206 "aboutprofiling-remote", 207 isSupportedPlatform, 208 supportedFeatures, 209 openRemoteDevTools 210 ); 211 } 212 213 get traits() { 214 return { ...this.client.mainRoot.traits }; 215 } 216 } 217 218 exports.ClientWrapper = ClientWrapper;