From 3736cbc4801806f052ab33eabe2d580f6d8fdb5a Mon Sep 17 00:00:00 2001 From: Michel Weststrate Date: Tue, 17 Aug 2021 07:50:43 -0700 Subject: [PATCH] Decouple JS device from Store Summary: Made a start with decoupling JS device. Incomplete as there are still Electron deps. Reviewed By: timur-valiev Differential Revision: D30309257 fbshipit-source-id: b8002170cbbe8d68e1795ce7c12ffce4c8eac853 --- desktop/app/src/dispatcher/flipperServer.tsx | 6 +- desktop/app/src/server/FlipperServer.tsx | 92 +++++++------------ .../app/src/server/comms/ServerController.tsx | 28 ++++-- .../server/devices/webapp/jsServerUtils.tsx | 26 ++---- 4 files changed, 63 insertions(+), 89 deletions(-) diff --git a/desktop/app/src/dispatcher/flipperServer.tsx b/desktop/app/src/dispatcher/flipperServer.tsx index de08b8eaa..0404c0fe2 100644 --- a/desktop/app/src/dispatcher/flipperServer.tsx +++ b/desktop/app/src/dispatcher/flipperServer.tsx @@ -10,14 +10,14 @@ import React from 'react'; import {Store} from '../reducers/index'; import {Logger} from '../fb-interfaces/Logger'; -import {startFlipperServer} from '../server/FlipperServer'; +import {FlipperServer} from '../server/FlipperServer'; import {selectClient, selectDevice} from '../reducers/connections'; import Client from '../Client'; import {notification} from 'antd'; export default async (store: Store, logger: Logger) => { const {enableAndroid, androidHome} = store.getState().settingsState; - const server = startFlipperServer( + const server = new FlipperServer( { enableAndroid, androidHome, @@ -101,7 +101,7 @@ export default async (store: Store, logger: Logger) => { } server - .waitForServerStarted() + .start() .then(() => { console.log( 'Flipper server started and accepting device / client connections', diff --git a/desktop/app/src/server/FlipperServer.tsx b/desktop/app/src/server/FlipperServer.tsx index 8509e23b8..8f552b033 100644 --- a/desktop/app/src/server/FlipperServer.tsx +++ b/desktop/app/src/server/FlipperServer.tsx @@ -48,18 +48,18 @@ export interface FlipperServerConfig { serverPorts: ServerPorts; } -export function startFlipperServer( - config: FlipperServerConfig, - store: Store, - logger: Logger, -): FlipperServer { - const server = new FlipperServer(config, store, logger); - server.start(); - return server; -} - type ServerState = 'pending' | 'starting' | 'started' | 'error' | 'closed'; +// defaultConfig should be used for testing only, and disables by default all features +const defaultConfig: FlipperServerConfig = { + androidHome: '', + enableAndroid: false, + serverPorts: { + insecure: -1, + secure: -1, + }, +}; + /** * FlipperServer takes care of all incoming device & client connections. * It will set up managers per device type, and create the incoming @@ -69,7 +69,10 @@ type ServerState = 'pending' | 'starting' | 'started' | 'error' | 'closed'; * using '.on'. All events are strongly typed. */ export class FlipperServer { + public config: FlipperServerConfig; + private readonly events = new EventEmitter(); + // server handles the incoming RSocket / WebSocket connections from Flipper clients readonly server: ServerController; readonly disposers: ((() => void) | void)[] = []; private readonly devices = new Map(); @@ -78,60 +81,14 @@ export class FlipperServer { // TODO: remove store argument constructor( - public config: FlipperServerConfig, + config: Partial, /** @deprecated remove! */ public store: Store, public logger: Logger, ) { - this.server = new ServerController(logger, store); + this.config = {...defaultConfig, ...config}; + const server = (this.server = new ServerController(this)); this.android = new AndroidDeviceManager(this); - } - - setServerState(state: ServerState, error?: Error) { - this.state = state; - this.emit('server-state', {state, error}); - } - - async waitForServerStarted() { - return new Promise((resolve, reject) => { - switch (this.state) { - case 'closed': - return reject(new Error('Server was closed already')); - case 'error': - return reject(new Error('Server has errored already')); - case 'started': - return resolve(); - default: { - const listener = ({ - state, - error, - }: { - state: ServerState; - error: Error; - }) => { - switch (state) { - case 'error': - return reject(error); - case 'started': - return resolve(); - case 'closed': - return reject(new Error('Server closed')); - } - this.events.off('server-state', listener); - }; - this.events.on('server-state', listener); - } - } - }); - } - - /** @private */ - async start() { - if (this.state !== 'pending') { - throw new Error('Server already started'); - } - this.setServerState('starting'); - const server = this.server; server.addListener('new-client', (client: Client) => { this.emit('client-connected', client); @@ -214,9 +171,24 @@ export class FlipperServer { ); }, ); + } + + setServerState(state: ServerState, error?: Error) { + this.state = state; + this.emit('server-state', {state, error}); + } + + /** + * Starts listening to parts and watching for devices + */ + async start() { + if (this.state !== 'pending') { + throw new Error('Server already started'); + } + this.setServerState('starting'); try { - await server.init(); + await this.server.init(); await this.startDeviceListeners(); this.setServerState('started'); } catch (e) { diff --git a/desktop/app/src/server/comms/ServerController.tsx b/desktop/app/src/server/comms/ServerController.tsx index b32b60a04..e26ec321a 100644 --- a/desktop/app/src/server/comms/ServerController.tsx +++ b/desktop/app/src/server/comms/ServerController.tsx @@ -34,6 +34,7 @@ import ServerAdapter, { ServerEventsListener, } from './ServerAdapter'; import {createBrowserServer, createServer} from './ServerFactory'; +import {FlipperServer} from '../FlipperServer'; type ClientInfo = { connection: ClientConnection | null | undefined; @@ -70,29 +71,38 @@ class ServerController extends EventEmitter implements ServerEventsListener { certificateProvider: CertificateProvider; connectionTracker: ConnectionTracker; - logger: Logger; - store: Store; + flipperServer: FlipperServer; timeHandler: NodeJS.Timeout | undefined; - constructor(logger: Logger, store: Store) { + constructor(flipperServer: FlipperServer) { super(); - this.logger = logger; + this.flipperServer = flipperServer; this.connections = new Map(); this.certificateProvider = new CertificateProvider( this, - logger, - store.getState().settingsState, + this.logger, + this.store.getState().settingsState, ); - this.connectionTracker = new ConnectionTracker(logger); + this.connectionTracker = new ConnectionTracker(this.logger); this.secureServer = null; this.insecureServer = null; this.browserServer = null; this.initialized = null; - this.store = store; this.timeHandler = undefined; } + get logger(): Logger { + return this.flipperServer.logger; + } + + /** + * @deprecated + */ + get store(): Store { + return this.flipperServer.store; + } + /** * Loads the secure server configuration and starts any necessary servers. * Initialisation is complete once the initialized promise is fullfilled at @@ -117,7 +127,7 @@ class ServerController extends EventEmitter implements ServerEventsListener { reportPlatformFailures(this.initialized, 'initializeServer'); if (GK.get('flipper_js_client_emulator')) { - initJsEmulatorIPC(this.store, this.logger, this, this.connections); + initJsEmulatorIPC(this.flipperServer, this.connections); } return this.initialized; diff --git a/desktop/app/src/server/devices/webapp/jsServerUtils.tsx b/desktop/app/src/server/devices/webapp/jsServerUtils.tsx index 1b8bcec69..8d27d1278 100644 --- a/desktop/app/src/server/devices/webapp/jsServerUtils.tsx +++ b/desktop/app/src/server/devices/webapp/jsServerUtils.tsx @@ -16,11 +16,8 @@ import { } from '../../comms/ClientConnection'; import {ipcRenderer, remote, IpcRendererEvent} from 'electron'; import JSDevice from './JSDevice'; -import {Store} from '../../../reducers'; -import {Logger} from '../../../fb-interfaces/Logger'; -import ServerController from '../../comms/ServerController'; import {buildClientId} from '../../../utils/clientUtils'; -import {destroyDevice} from '../../../reducers/connections'; +import {FlipperServer} from '../../FlipperServer'; const connections: Map = new Map(); @@ -31,9 +28,7 @@ function jsDeviceId(windowId: number): string { } export function initJsEmulatorIPC( - store: Store, - logger: Logger, - flipperServer: ServerController, + flipperServer: FlipperServer, flipperConnections: Map< string, { @@ -48,10 +43,7 @@ export function initJsEmulatorIPC( const {windowId} = message; const {plugins, appName} = message.payload; const device = new JSDevice(jsDeviceId(windowId), 'jsEmulator', windowId); - store.dispatch({ - type: 'REGISTER_DEVICE', - payload: device, - }); + flipperServer.registerDevice(device); const connection = new JSClientFlipperConnection(windowId); connections.set(windowId, connection); @@ -70,8 +62,8 @@ export function initJsEmulatorIPC( clientId, query, connection, - logger, - store, + flipperServer.logger, + flipperServer.store, plugins, device, ); @@ -87,8 +79,8 @@ export function initJsEmulatorIPC( status == ConnectionStatus.CLOSED ) { console.debug(`Device disconnected ${client.id}`, 'server'); - flipperServer.removeConnection(client.id); - destroyDevice(store, logger, jsDeviceId(windowId)); + flipperServer.server.removeConnection(client.id); + flipperServer.unregisterDevice(jsDeviceId(windowId)); connections.delete(windowId); availablePlugins.delete(windowId); } @@ -98,8 +90,8 @@ export function initJsEmulatorIPC( .init() .then(() => { console.log(client); - flipperServer.emit('new-client', client); - flipperServer.emit('clients-change'); + flipperServer.server.emit('new-client', client); + flipperServer.server.emit('clients-change'); client.emit('plugins-change'); ipcRenderer.on(