Decouple CertificateProvider and adb/idb client intialization

Summary:
Previously CertificateProvider initialized ADB and provided config to IDB. As result, AndroidDeviceManager and iOSDeviceManager indirectly depended on CertificateProvider.

With this diff we:
1. Make idbConfig resemble adbClient.
2. Make AndroidDeviceManager and iOSDeviceManager initialize their own clients
3. Fix server crash when one of the clients couldn't be initialized. The reason for the crash is CertificateProvider.prototype.init which is no longer needed.

Reviewed By: passy

Differential Revision: D33711652

fbshipit-source-id: 055b5625ed993827b65396f4af5157808479242b
This commit is contained in:
Andrey Goncharov
2022-01-26 03:57:46 -08:00
committed by Facebook GitHub Bot
parent 1255621cba
commit da618fd3f3
9 changed files with 101 additions and 72 deletions

View File

@@ -13,19 +13,29 @@ import adbConfig from './adbConfig';
import adbkit, {Client} from 'adbkit';
import path from 'path';
let instance: Client;
let instance: Client | undefined;
type Config = {
androidHome: string;
};
export async function getAdbClient(config: Config): Promise<Client> {
if (!instance) {
instance = await reportPlatformFailures(
createClient(config),
'createADBClient',
export function getAdbClient(): Client | undefined {
return instance;
}
export async function setAdbClient(
config: Config,
): Promise<Client | undefined> {
instance = await reportPlatformFailures(
createClient(config),
'createADBClient',
).catch((e) => {
console.warn(
'Failed to initialize ADB. Please disable Android support in settings, or configure a correct path.',
e,
);
}
return undefined;
});
return instance;
}

View File

@@ -10,9 +10,7 @@
import AndroidDevice from './AndroidDevice';
import KaiOSDevice from './KaiOSDevice';
import child_process from 'child_process';
import {getAdbClient} from './adbClient';
import which from 'which';
import {promisify} from 'util';
import {setAdbClient} from './adbClient';
import {Client as ADBClient, Device} from 'adbkit';
import {join} from 'path';
import {FlipperServerImpl} from '../../FlipperServerImpl';
@@ -172,7 +170,13 @@ export class AndroidDeviceManager {
async watchAndroidDevices() {
try {
const client = await getAdbClient(getFlipperServerConfig().settings);
const client = await setAdbClient(getFlipperServerConfig().settings);
if (!client) {
throw new Error(
'AndroidDeviceManager.watchAndroidDevices -> adb not initialized',
);
}
client
.trackDevices()
.then((tracker) => {

View File

@@ -72,6 +72,7 @@ test('test getAllPromisesForQueryingDevices when xcode detected', () => {
getLogger(),
);
flipperServer.ios.iosBridge = {} as IOSBridge;
(flipperServer.ios as any).idbConfig = getFlipperServerConfig().settings;
const promises = flipperServer.ios.getAllPromisesForQueryingDevices(
true,
false,
@@ -85,6 +86,7 @@ test('test getAllPromisesForQueryingDevices when xcode is not detected', () => {
getLogger(),
);
flipperServer.ios.iosBridge = {} as IOSBridge;
(flipperServer.ios as any).idbConfig = getFlipperServerConfig().settings;
const promises = flipperServer.ios.getAllPromisesForQueryingDevices(
false,
true,
@@ -98,6 +100,7 @@ test('test getAllPromisesForQueryingDevices when xcode and idb are both unavaila
getLogger(),
);
flipperServer.ios.iosBridge = {} as IOSBridge;
(flipperServer.ios as any).idbConfig = getFlipperServerConfig().settings;
const promises = flipperServer.ios.getAllPromisesForQueryingDevices(
false,
false,
@@ -111,6 +114,7 @@ test('test getAllPromisesForQueryingDevices when both idb and xcode are availabl
getLogger(),
);
flipperServer.ios.iosBridge = {} as IOSBridge;
(flipperServer.ios as any).idbConfig = getFlipperServerConfig().settings;
const promises = flipperServer.ios.getAllPromisesForQueryingDevices(
true,
true,

View File

@@ -148,6 +148,7 @@ async function targets(
if (process.platform !== 'darwin') {
return [];
}
const isXcodeInstalled = await isXcodeDetected();
if (!isXcodeInstalled) {
if (!isPhysicalDeviceEnabled) {
@@ -203,6 +204,7 @@ async function push(
idbPath: string,
): Promise<void> {
await memoize(checkIdbIsInstalled)(idbPath);
return wrapWithErrorMessage(
reportPlatformFailures(
safeExec(
@@ -225,6 +227,7 @@ async function pull(
idbPath: string,
): Promise<void> {
await memoize(checkIdbIsInstalled)(idbPath);
return wrapWithErrorMessage(
reportPlatformFailures(
safeExec(

View File

@@ -22,6 +22,8 @@ import {
import {FlipperServerImpl} from '../../FlipperServerImpl';
import {notNull} from '../../utils/typeUtils';
import {getFlipperServerConfig} from '../../FlipperServerConfig';
import {IdbConfig, setIdbConfig} from './idbConfig';
import {assertNotNull} from 'flipper-server-core/src/comms/Utilities';
type iOSSimulatorDevice = {
state: 'Booted' | 'Shutdown' | 'Shutting Down';
@@ -44,6 +46,7 @@ function isAvailable(simulator: iOSSimulatorDevice): boolean {
export class IOSDeviceManager {
private portForwarders: Array<ChildProcess> = [];
private idbConfig?: IdbConfig;
private portforwardingClient = path.join(
getFlipperServerConfig().paths.staticPath,
@@ -107,14 +110,15 @@ export class IOSDeviceManager {
isXcodeDetected: boolean,
isIdbAvailable: boolean,
): Array<Promise<any>> {
const config = getFlipperServerConfig().settings;
assertNotNull(this.idbConfig);
return [
isIdbAvailable
? getActiveDevices(config.idbPath, config.enablePhysicalIOS).then(
(devices: IOSDeviceParams[]) => {
this.processDevices(devices);
},
)
? getActiveDevices(
this.idbConfig.idbPath,
this.idbConfig.enablePhysicalIOS,
).then((devices: IOSDeviceParams[]) => {
this.processDevices(devices);
})
: null,
!isIdbAvailable && isXcodeDetected
? this.getSimulators(true).then((devices) =>
@@ -126,9 +130,9 @@ export class IOSDeviceManager {
}
private async queryDevices(): Promise<any> {
const config = getFlipperServerConfig().settings;
assertNotNull(this.idbConfig);
const isXcodeInstalled = await iosUtil.isXcodeDetected();
const isIdbAvailable = await iosUtil.isAvailable(config.idbPath);
const isIdbAvailable = await iosUtil.isAvailable(this.idbConfig.idbPath);
console.debug(
`[conn] queryDevices. isXcodeInstalled ${isXcodeInstalled}, isIdbAvailable ${isIdbAvailable}`,
);
@@ -177,11 +181,8 @@ export class IOSDeviceManager {
}
public async watchIOSDevices() {
// TODO: pull this condition up
const settings = getFlipperServerConfig().settings;
if (!settings.enableIOS) {
return;
}
this.idbConfig = setIdbConfig(settings);
try {
const isDetected = await iosUtil.isXcodeDetected();
this.xcodeCommandLineToolsDetected = isDetected;

View File

@@ -0,0 +1,22 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
export type IdbConfig = {
idbPath: string;
enablePhysicalIOS: boolean;
};
let idbConfig: IdbConfig | undefined;
export const getIdbConfig = () => idbConfig;
export const setIdbConfig = (newIdbConfig: IdbConfig) => {
idbConfig = newIdbConfig;
return idbConfig;
};