in desktop/flipper-dump/src/index.tsx [71:245]
async function start(deviceQuery: string, appName: string, pluginId: string) {
return new Promise(async (_resolve, reject) => {
const staticPath = path.resolve(__dirname, '..', '..', 'static');
let device: DeviceDescription | undefined;
let deviceResolver: () => void;
const devicePromise: Promise<void> = new Promise((resolve) => {
deviceResolver = resolve;
});
let client: ClientDescription | undefined;
const logger = createLogger();
setLoggerInstance(logger);
// avoid logging to STDOUT!
console.log = console.error;
console.debug = () => {};
console.info = console.error;
const environmentInfo = await getEnvironmentInfo(staticPath, false);
// TODO: initialise FB user manager to be able to do certificate exchange
const server = new FlipperServerImpl(
{
environmentInfo,
env: parseEnvironmentVariables(process.env),
gatekeepers: {},
paths: {
staticPath,
tempPath: os.tmpdir(),
appPath: `/dev/null`,
homePath: `/dev/null`,
execPath: process.execPath,
desktopPath: `/dev/null`,
},
launcherSettings: await loadLauncherSettings(argv.launcherSettings),
processConfig: loadProcessConfig(process.env),
settings: await loadSettings(argv.settingsString),
validWebSocketOrigins: [],
},
logger,
);
logger.info(
`Waiting for device '${deviceQuery}' client '${appName}' plugin '${pluginId}' ...`,
);
server.on('notification', ({type, title, description}) => {
if (type === 'error') {
reject(new Error(`${title}: ${description}`));
}
});
server.on('server-error', reject);
server.on('server-state', ({state, error}) => {
if (state === 'error') {
reject(error);
}
});
server.on('device-connected', (deviceInfo) => {
logger.info(
`Detected device [${deviceInfo.os}] ${deviceInfo.title} ${deviceInfo.serial}`,
);
if (deviceInfo.serial == deviceQuery) {
logger.info(`Device matched on device serial ${deviceQuery}`);
device = deviceInfo;
deviceResolver();
} else if (deviceInfo.title === deviceQuery) {
logger.info(`Device matched on device title ${deviceQuery}`);
device = deviceInfo;
deviceResolver();
}
});
server.on('device-disconnected', (deviceInfo) => {
if (device && deviceInfo.serial === device.serial) {
reject(new Error('Device disconnected: ' + deviceInfo.serial));
}
});
server.on('client-setup', (client) => {
logger.info(
`Connection attempt: ${client.appName} on ${client.deviceName}`,
);
});
server.on(
'client-connected',
async (clientDescription: ClientDescription) => {
// device matching is promisified, as we clients can arrive before device is detected
await devicePromise;
if (clientDescription.query.app === appName) {
if (clientDescription.query.device_id === device!.serial) {
logger.info(`Client matched: ${clientDescription.id}`);
client = clientDescription;
try {
// fetch plugins
const response = await server.exec(
'client-request-response',
client.id,
{
method: 'getPlugins',
},
);
logger.info(JSON.stringify(response));
if (response.error) {
reject(response.error);
return;
}
const plugins: string[] = (response.success as any).plugins;
logger.info('Detected plugins ' + plugins.join(','));
if (!plugins.includes(pluginId)) {
// TODO: what if it only registers later?
throw new Error(
`Plugin ${pluginId} was not registered on client ${client.id}`,
);
}
logger.info(`Starting plugin ` + pluginId);
const response2 = await server.exec(
'client-request-response',
client.id,
{
method: 'init',
params: {plugin: pluginId},
},
);
if (response2.error) {
reject(response2.error);
}
logger.info('Plugin initialised');
} catch (e) {
reject(e);
}
}
}
},
);
server.on('client-disconnected', ({id}) => {
if (id === client?.id) {
// TODO: maybe we need a flag to signal that this might be undesired?
logger.info('Target application disconnected, exiting...');
process.exit(0);
}
});
server.on('client-message', ({id, message}) => {
if (id === client?.id) {
const parsed = JSON.parse(message);
if (parsed.method === 'execute') {
if (parsed.params.api === pluginId) {
// TODO: customizable format
stdout.write(
`\n\n\n[${parsed.params.method}]\n${JSON.stringify(
parsed.params.params,
null,
2,
)}\n`,
);
}
} else {
logger.warn('Dropping message ', message);
}
}
});
server
.connect()
.then(() => {
logger.info(
'Flipper server started and accepting device / client connections',
);
})
.catch(reject);
});
}