diff --git a/desktop/app/src/init.tsx b/desktop/app/src/init.tsx index 674c4cdab..7bd524c4c 100644 --- a/desktop/app/src/init.tsx +++ b/desktop/app/src/init.tsx @@ -96,7 +96,6 @@ async function start() { keytar, ); - await flipperServer.connect(); const flipperServerConfig = await flipperServer.exec('get-config'); initializeElectron(flipperServer, flipperServerConfig); @@ -110,6 +109,8 @@ async function start() { // eslint-disable-next-line import/no-commonjs require('flipper-ui-core').startFlipperDesktop(flipperServer); + await flipperServer.connect(); + // Initialize launcher setupPrefetcher(flipperServerConfig.settings); } diff --git a/desktop/flipper-server-core/src/comms/ServerController.tsx b/desktop/flipper-server-core/src/comms/ServerController.tsx index dbcf1ae40..7745a0be3 100644 --- a/desktop/flipper-server-core/src/comms/ServerController.tsx +++ b/desktop/flipper-server-core/src/comms/ServerController.tsx @@ -71,15 +71,14 @@ interface ServerController { * Additionally, it manages client connections. */ class ServerController extends EventEmitter implements ServerEventsListener { - connections: Map; - timestamps: Map; + connections: Map = new Map(); + timestamps: Map = new Map(); - initialized: Promise | null; - secureServer: Promise | null; - insecureServer: Promise | null; - altSecureServer: Promise | null; - altInsecureServer: Promise | null; - browserServer: Promise | null; + secureServer: ServerAdapter | null = null; + insecureServer: ServerAdapter | null = null; + altSecureServer: ServerAdapter | null = null; + altInsecureServer: ServerAdapter | null = null; + browserServer: ServerAdapter | null = null; certificateProvider: CertificateProvider; connectionTracker: ConnectionTracker; @@ -91,19 +90,11 @@ class ServerController extends EventEmitter implements ServerEventsListener { constructor(flipperServer: FlipperServerImpl) { super(); this.flipperServer = flipperServer; - this.connections = new Map(); - this.timestamps = new Map(); this.certificateProvider = new CertificateProvider( this, getFlipperServerConfig().settings, ); this.connectionTracker = new ConnectionTracker(this.logger); - this.secureServer = null; - this.insecureServer = null; - this.altSecureServer = null; - this.altInsecureServer = null; - this.browserServer = null; - this.initialized = null; } onClientMessage(clientId: string, payload: string): void { @@ -122,69 +113,57 @@ class ServerController extends EventEmitter implements ServerEventsListener { * Initialisation is complete once the initialized promise is fullfilled at * which point Flipper is accepting connections. */ - init() { + async init() { if (isTest()) { throw new Error('Spawing new server is not supported in test'); } + this.certificateProvider.init(); const {insecure, secure} = getServerPortsConfig().serverPorts; - this.initialized = this.certificateProvider - .loadSecureServerConfig() - .then((options) => { - console.info('[conn] secure server listening at port: ', secure); - this.secureServer = createServer(secure, this, options); - const {secure: altSecure} = getServerPortsConfig().altServerPorts; - console.info( - '[conn] secure server (ws) listening at port: ', - altSecure, - ); - this.altSecureServer = createServer( - altSecure, - this, - options, - TransportType.WebSocket, - ); - }) - .then(() => { - console.info('[conn] insecure server listening at port: ', insecure); - this.insecureServer = createServer(insecure, this); - const {insecure: altInsecure} = getServerPortsConfig().altServerPorts; - console.info( - '[conn] insecure server (ws) listening at port: ', - altInsecure, - ); - this.altInsecureServer = createServer( - altInsecure, - this, - undefined, - TransportType.WebSocket, - ); - return; - }); + const options = await this.certificateProvider.loadSecureServerConfig(); + + console.info('[conn] secure server listening at port: ', secure); + this.secureServer = await createServer(secure, this, options); + const {secure: altSecure} = getServerPortsConfig().altServerPorts; + console.info('[conn] secure server (ws) listening at port: ', altSecure); + this.altSecureServer = await createServer( + altSecure, + this, + options, + TransportType.WebSocket, + ); + + console.info('[conn] insecure server listening at port: ', insecure); + this.insecureServer = await createServer(insecure, this); + const {insecure: altInsecure} = getServerPortsConfig().altServerPorts; + console.info( + '[conn] insecure server (ws) listening at port: ', + altInsecure, + ); + this.altInsecureServer = await createServer( + altInsecure, + this, + undefined, + TransportType.WebSocket, + ); if (GK.get('comet_enable_flipper_connection')) { console.info('[conn] Browser server (ws) listening at port: ', 8333); - this.browserServer = createBrowserServer(8333, this); + this.browserServer = await createBrowserServer(8333, this); } - - reportPlatformFailures(this.initialized, 'initializeServer'); - - return this.initialized; } /** * If initialized, it stops any started servers. */ async close() { - if (this.initialized && (await this.initialized)) { - await Promise.all([ - this.insecureServer && (await this.insecureServer).stop(), - this.secureServer && (await this.secureServer).stop(), - this.altInsecureServer && (await this.altInsecureServer).stop(), - this.altSecureServer && (await this.altSecureServer).stop(), - this.browserServer && (await this.browserServer).stop(), - ]); - } + await Promise.all([ + this.insecureServer?.stop(), + this.secureServer?.stop(), + this.altInsecureServer?.stop(), + this.altSecureServer?.stop(), + this.browserServer?.stop(), + ]); } onConnectionCreated( diff --git a/desktop/flipper-server-core/src/utils/CertificateProvider.tsx b/desktop/flipper-server-core/src/utils/CertificateProvider.tsx index 9680b3356..0a647beba 100644 --- a/desktop/flipper-server-core/src/utils/CertificateProvider.tsx +++ b/desktop/flipper-server-core/src/utils/CertificateProvider.tsx @@ -89,12 +89,12 @@ type CertificateProviderConfig = { * Flipper CA. */ export default class CertificateProvider { - private _adb: Promise | undefined; + private _adb: ADBClient | undefined; private didCertificateSetup = false; private config: CertificateProviderConfig; private server: ServerController; - get adb(): Promise { + get adb(): ADBClient { if (this.config.enableAndroid) { if (this._adb) { return this._adb; @@ -105,22 +105,25 @@ export default class CertificateProvider { } constructor(server: ServerController, config: CertificateProviderConfig) { - // TODO: refactor this code to create promise lazily - this._adb = config.enableAndroid - ? (getAdbClient(config).catch((_e) => { - // make sure initialization failure is already logged - const msg = - 'Failed to initialize ADB. Please disable Android support in settings, or configure a correct path'; - server.flipperServer.emit('notification', { - type: 'error', - title: 'Failed to initialise ADB', - description: msg, - }); - this._adb = undefined; // no adb client available - }) as Promise) - : undefined; - this.config = config; this.server = server; + this.config = config; + } + + async init() { + if (this.config.enableAndroid) { + try { + this._adb = await getAdbClient(this.config); + } catch (_e) { + // make sure initialization failure is already logged + const msg = + 'Failed to initialize ADB. Please disable Android support in settings, or configure a correct path'; + this.server.flipperServer.emit('notification', { + type: 'error', + title: 'Failed to initialise ADB', + description: msg, + }); + } + } } private uploadFiles = async ( @@ -255,10 +258,9 @@ export default class CertificateProvider { private async ensureOpenSSLIsAvailable(): Promise { if (!(await opensslInstalled())) { - const e = Error( + throw new Error( "It looks like you don't have OpenSSL installed. Please install it to continue.", ); - this.server.emit('error', e); } } @@ -321,9 +323,8 @@ export default class CertificateProvider { destination, csr, ); - const adbClient = await this.adb; await androidUtil.push( - adbClient, + this.adb, deviceId, appName, destination + filename, @@ -379,7 +380,7 @@ export default class CertificateProvider { deviceCsrFilePath: string, csr: string, ): Promise { - const devicesInAdb = await this.adb.then((client) => client.listDevices()); + const devicesInAdb = await this.adb.listDevices(); if (devicesInAdb.length === 0) { throw new Error('No Android devices found'); } @@ -472,9 +473,8 @@ export default class CertificateProvider { processName: string, csr: string, ): Promise<{isMatch: boolean; foundCsr: string}> { - const adbClient = await this.adb; const deviceCsr = await androidUtil.pull( - adbClient, + this.adb, deviceId, processName, directory + csrFileName, @@ -590,6 +590,7 @@ export default class CertificateProvider { } async loadSecureServerConfig(): Promise { + await this.ensureOpenSSLIsAvailable(); await this.certificateSetup(); return { key: await fs.readFile(serverKey),