diff --git a/.todo.js b/.todo.js new file mode 100644 index 0000000..5787fbb --- /dev/null +++ b/.todo.js @@ -0,0 +1,2 @@ +// TODO Search adb exists in default folders before each command +// TODO Check and execute adb commands in adb bin folder. diff --git a/README.md b/README.md index d9fbf62..5248292 100644 --- a/README.md +++ b/README.md @@ -3,17 +3,23 @@ ![GitHub](https://img.shields.io/github/license/vinicioslc/adb-interface-vscode?style=flat-square) ![Visual Studio Marketplace Installs](https://img.shields.io/visual-studio-marketplace/i/vinicioslc.adb-interface-vscode?style=flat-square) ![Visual Studio Marketplace Rating (Stars)](https://img.shields.io/visual-studio-marketplace/stars/vinicioslc.adb-interface-vscode?style=flat-square) -[![Codacy Badge](https://api.codacy.com/project/badge/Grade/308ff6c762d14642bdeb903dd7bfa552)](https://www.codacy.com/manual/vinicioslc/adb-interface-vscode?utm_source=github.com&utm_medium=referral&utm_content=vinicioslc/adb-interface-vscode&utm_campaign=Badge_Grade) + + # ADB Interface for VSCode -⚠️ WARN !! ONLY TESTED IN WINDOWS !! (For while, you must have ADB at your Enviroment Variables) +> ⚠️ WARN !! ONLY TESTED IN WINDOWS !! (For while, you must have ADB at your Enviroment Variables) + +This are an simple ADB-Wrapper that makes possible to connect to an device over wifi connection without console use. Help are welcome ;) -You can contribute with [Code](https://github.com/) or [Energy](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=TKRZ7F4FV4QY4&source=url) +You can contribute with +[Code](https://github.com/vinicioslc/adb-interface-vscode) +or +[Energy](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=TKRZ7F4FV4QY4&source=url) -This are an simple ADB-Wrapper that makes possible to connect to an device over wifi connection without console use. +[简体中文指南](https://www.jianshu.com/p/fb8eebc8a2c0) ## Features Todo/Done @@ -21,7 +27,7 @@ This are an simple ADB-Wrapper that makes possible to connect to an device over ☒ Kills the adb server and all current connections -- ☐ ADB Resolver +- ☐ ADB Resolver - Find and resolve ADB Location ☒ Use default `ADB` in Enviroment Variable @@ -38,9 +44,7 @@ This are an simple ADB-Wrapper that makes possible to connect to an device over ![status bar](media/record1.gif) -### Tests Health Summary - -> Generated by jest-badge-generator +### Tests Health Summary by jest-badge-generator ![coverage-branches](https://raw.githubusercontent.com/vinicioslc/adb-interface-vscode/master/.badges/badge-branches.png) ![coverage-function](https://raw.githubusercontent.com/vinicioslc/adb-interface-vscode/master/.badges/badge-functions.png) @@ -49,7 +53,7 @@ This are an simple ADB-Wrapper that makes possible to connect to an device over ## Available Commands -- ADB:📱 Reset connected devices port to :5555 (Open device port with `adb tcpip 5555`) +- ADB:📱 Reset connected devices port to :5555 (Open current device port with `adb tcpip 5555`) - ADB:📱 Connect to device IP (need inform IP from device wanted `adb connect ${user_ip}:5555`) - ADB:📱 Disconnect from any devices (Disconnect ever device attached `adb disconnect`) - ADB:📱 Connect to device from List (Show an list from devices attached to connect) diff --git a/package.json b/package.json index d80b36c..af80da0 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "publisher": "vinicioslc", "repository": "https://github.com/vinicioslc/adb-interface-vscode", "engines": { - "vscode": "^1.25.0" + "vscode": "^1.26.0" }, "icon": "media/icon.png", "galleryBanner": { diff --git a/src/__tests__/connect-device-suite.test.ts b/src/__tests__/connect-device-suite.test.ts index 3f3b179..3814e50 100644 --- a/src/__tests__/connect-device-suite.test.ts +++ b/src/__tests__/connect-device-suite.test.ts @@ -1,44 +1,32 @@ -import { ADBChannel, ADBInterfaceException } from '../adb-wrapper' +import { ADBConnection, ADBInterfaceException } from '../adb-wrapper' import { ConsoleInterfaceMock } from '../console/console-interface/console-interface-mock' -import adbCommands from '../adb-wrapper/adb-commands' -// Mocked ConsoleInterface -let cimock = new ConsoleInterfaceMock() -let adbInterfaceInstance = new ADBChannel(cimock) +const ip = '192.168.1.102' +const phoneName = 'DEVICE_NAME' -test('will connect to device seamless', async () => { - const connectDeviceIp = '192.168.1.100' - const connectExistingDeviceMock = (input: string) => { - if (input == `adb -s ${connectDeviceIp} shell getprop ro.product.model`) { - return Buffer.from('PEAR_PHONE') - } else if (input === adbCommands.CONNECT_IP_AND_PORT(connectDeviceIp)) { - return Buffer.from(`connected to ${connectDeviceIp}`) - } else { - return Buffer.from(`fail`) - } - } - cimock.setCallbackMock(connectExistingDeviceMock) - const result = await adbInterfaceInstance.ConnectToDevice(connectDeviceIp) +test('Connect to device with success', async () => { + let cimock = new ConsoleInterfaceMock() + let adbInterfaceInstance = new ADBConnection(cimock) + + cimock.setConsoleOutput(`Android Debug Bridge`) + cimock.setConsoleOutput(`connected to ${ip}`) + cimock.setConsoleOutput('PEAR_PHONE') + cimock.returnInfinity = true - expect(result.message).toStrictEqual(`Connected to: PEAR_PHONE`) + const { message } = await adbInterfaceInstance.ConnectToDevice(ip) + + expect(message).toStrictEqual(`Connected to: PEAR_PHONE`) }) -test('allready connected to another device', async () => { +test('Fail to connect when allready connected', async () => { try { - const allreadyConnectedIP = '192.168.1.102' - const allreadyConnectedPhoneName = 'DEVICE_NAME' - const allreadyConnectedCallback = (input: string) => { - if (input == `adb -s 192.168.1.102 shell getprop ro.product.model`) { - return Buffer.from(allreadyConnectedPhoneName) - } else if (input === `adb connect 192.168.1.102:5555`) { - return Buffer.from(`already connected to 192.168.1.102`) - } else { - return Buffer.from(`fail`) - } - } - - cimock.setCallbackMock(allreadyConnectedCallback) - await adbInterfaceInstance.ConnectToDevice(allreadyConnectedIP) + let cimock = new ConsoleInterfaceMock() + let adbInterfaceInstance = new ADBConnection(cimock) + cimock.returnInfinity = true + cimock.setConsoleOutput(`Android Debug Bridge`) + cimock.setConsoleOutput(`already connected to ${ip}`) + cimock.setConsoleOutput(phoneName) + await adbInterfaceInstance.ConnectToDevice(ip) } catch (e) { expect(e).toBeInstanceOf(ADBInterfaceException) } diff --git a/src/__tests__/firebase-manager.test.ts b/src/__tests__/firebase-manager.test.ts index 27632cd..929fb0a 100644 --- a/src/__tests__/firebase-manager.test.ts +++ b/src/__tests__/firebase-manager.test.ts @@ -1,12 +1,5 @@ -import { - ADBChannel, - ADBResultState, - ADBResult, - ADBInterfaceError, - ADBInterfaceException -} from '../adb-wrapper' +import { ADBResultState, ADBInterfaceError } from '../adb-wrapper' import { ConsoleInterfaceMock } from '../console/console-interface/console-interface-mock' -// import { ConsoleInterface } from './../console-interface/console-interface' import { FirebaseManagerChannel } from './../firebase-actions/index' // Mocked ConsoleInterface @@ -39,10 +32,12 @@ test('No Devices informed', async () => { }) test('Disable firebase debugview', async () => { - cimock.setConsoleOutput('') - const result = await adbInterfaceInstance.disableFirebaseDebugView() - - expect(result.state).toStrictEqual(ADBResultState.Success) + try { + cimock.setConsoleOutput('') + const result = await adbInterfaceInstance.disableFirebaseDebugView() + } catch (e) { + expect(e).toBeInstanceOf(ADBInterfaceError) + } }) test('Enable firebase debugview success', async () => { diff --git a/src/__tests__/kill-adb-suite.test.ts b/src/__tests__/kill-adb-suite.test.ts index 3cfae68..ba64f10 100644 --- a/src/__tests__/kill-adb-suite.test.ts +++ b/src/__tests__/kill-adb-suite.test.ts @@ -1,19 +1,25 @@ -import { ADBChannel, ADBResultState, ADBResult } from '../adb-wrapper' +import { + ADBConnection, + ADBResultState, + ADBResult, + ADBInterfaceError +} from '../adb-wrapper' import { ConsoleInterfaceMock } from '../console/console-interface/console-interface-mock' // import { ConsoleInterface } from './../console-interface/console-interface' // Mocked ConsoleInterface const cimock = new ConsoleInterfaceMock() -const adbInterfaceInstance = new ADBChannel(cimock) +const adbInterfaceInstance = new ADBConnection(cimock) test('Test ADB Server has killed', async () => { - cimock.setConsoleOutput('') - const result = await adbInterfaceInstance.KillADBServer() + const expected = new ADBResult(ADBResultState.Success, 'ADB Server killed') + try { + cimock.setConsoleOutput('') + cimock.setConsoleOutput(`Android Debug Bridge`) - const expected = await new ADBResult( - ADBResultState.Success, - 'ADB Server killed' - ) - - expect(JSON.stringify(result)).toBe(JSON.stringify(expected)) + const result = await adbInterfaceInstance.KillADBServer() + expect(JSON.stringify(result)).toBe(JSON.stringify(expected)) + } catch (e) { + expect(e).toBeInstanceOf(ADBInterfaceError) + } }) diff --git a/src/__tests__/list-adb-suite.test.ts b/src/__tests__/list-adb-suite.test.ts index 14d45fb..30ae499 100644 --- a/src/__tests__/list-adb-suite.test.ts +++ b/src/__tests__/list-adb-suite.test.ts @@ -1,18 +1,19 @@ -import { ADBChannel, ADBResultState, ADBResult } from '../adb-wrapper' +import { ADBConnection } from '../adb-wrapper' import { ConsoleInterfaceMock } from '../console/console-interface/console-interface-mock' -// import { ConsoleInterface } from './../console-interface/console-interface' - -// Mocked ConsoleInterface -const cimock = new ConsoleInterfaceMock() -const adbInterfaceInstance = new ADBChannel(cimock) test('Test ADB Listed Devices', async () => { - cimock.setConsoleOutput(`* daemon not running; starting now at tcp:5037 + let cimock = new ConsoleInterfaceMock() + let adbInterfaceInstance = new ADBConnection(cimock) + cimock.setConsoleOutput(`Android Debug Bridge`) + cimock.setConsoleOutput(`* starting now at tcp:5037 * daemon started successfully - List of devices attached - + List of devices attached + 2ab7dcd77d04 unauthorized `) - const result = await adbInterfaceInstance.FindConnectedDevices() + cimock.setConsoleOutput(`PEAR_PHONE`) + cimock.returnInfinity = true + + let result = await adbInterfaceInstance.FindConnectedDevices() - expect(typeof result).toStrictEqual(typeof Array()) -}) + expect(result instanceof Array).toBe(true) +}, 12000) diff --git a/src/adb-resolver/common-resolver.test.ts b/src/adb-resolver/common-resolver.test.ts new file mode 100644 index 0000000..6098b48 --- /dev/null +++ b/src/adb-resolver/common-resolver.test.ts @@ -0,0 +1,36 @@ +import * as os from 'os' +import { ADBResolver, ADBNotFoundError } from './index' +import { ConsoleInterfaceMock } from '../console/console-interface/console-interface-mock' +const adbInEnvReturn = `Android Debug Bridge version 1.0.41 +Version 29.0.1-5644136 +Installed as C:\Users\vinic\AppData\Local\Android\Sdk\platform-tools\adb.exe + +global options:` + +test('Should return current home dir when path is present', async () => { + const consoleMock = new ConsoleInterfaceMock() + consoleMock.setConsoleOutput(adbInEnvReturn) + const adbResolver = new ADBResolver(os.homedir(), os.type(), consoleMock) + + expect(await adbResolver.getDefaultADBPath()).toBe(os.homedir()) +}) + +test('Throw error when nothing found', () => { + try { + const consoleMock = new ConsoleInterfaceMock() + consoleMock.setConsoleOutput(`Invalid Return`) + const adbResolver = new ADBResolver(os.homedir(), os.type(), consoleMock) + } catch (error) { + expect(error).toBeInstanceOf(ADBNotFoundError) + } +}) + +test('Should return path to adb', async () => { + const consoleMock = new ConsoleInterfaceMock() + consoleMock.returnInfinity = false + consoleMock.setConsoleOutput(`Invalid Return`) + consoleMock.setConsoleOutput(adbInEnvReturn) + const adbResolver = new ADBResolver('yourhome', 'Linux', consoleMock) + let adbPath = await adbResolver.getDefaultADBPath() + expect(adbPath).toBe('yourhome/Android/Sdk') +}) diff --git a/src/adb-shell-resolver/index.ts b/src/adb-resolver/helper-functions.ts similarity index 61% rename from src/adb-shell-resolver/index.ts rename to src/adb-resolver/helper-functions.ts index b901ca0..a03c627 100644 --- a/src/adb-shell-resolver/index.ts +++ b/src/adb-resolver/helper-functions.ts @@ -1,19 +1,23 @@ import * as os from 'os' -// TODO Verificar e executar comandos adb na pasta indicada. -const getAndroidStudioPath = ({ osType, homeDir }) => { +import * as path from 'path' + +export const getAndroidStudioPath = ({ osType, homeDir }) => { switch (osType) { case 'Windows_NT': - return `${homeDir}/AppData/Local/Android/Sdk/platform-tools` + return path.win32.join( + homeDir, + '/AppData/Local/Android/Sdk/platform-tools' + ) case 'Darwin': - return `${homeDir}/Library/Android/sdk/platform-tools` + return path.posix.join(homeDir, '/Library/Android/sdk/platform-tools') case 'Linux': - return `${homeDir}/Android/Sdk` + return path.posix.join(homeDir, '/Android/Sdk') default: throw new TypeError('Android Path Error: Invalid Platform') } } -const getDownloadADBUrl = ({ osType }) => { +export const getDownloadADBUrl = ({ osType }) => { switch (osType) { case 'Windows_NT': return 'https://dl.google.com/android/repository/platform-tools-latest-windows.zip' diff --git a/src/adb-resolver/index.ts b/src/adb-resolver/index.ts new file mode 100644 index 0000000..1d7246c --- /dev/null +++ b/src/adb-resolver/index.ts @@ -0,0 +1,62 @@ +import * as path from 'path' +import * as os from 'os' +import { ConsoleInterface } from '../console/console-interface' +import * as helperFunctions from './helper-functions' + +export class ADBResolver { + homeDir: string + osType: string + consoleInterface: ConsoleInterface + + private readonly successADBReturn = 'Android Debug Bridge' + + constructor( + homeDir: string, + osType: string, + consoleInterfaceInstance: ConsoleInterface + ) { + this.homeDir = homeDir + this.osType = osType + this.consoleInterface = consoleInterfaceInstance + } + + private async hasAndroidInEnv(): Promise { + const result = await this.consoleInterface.execConsoleSync('adb') + return result.toLocaleString().includes(this.successADBReturn) + } + private returnDefaultADBPath(): string { + return helperFunctions.getAndroidStudioPath({ + osType: this.osType, + homeDir: this.homeDir + }) + } + + private async hasPlatformToolsDefaultFolder(): Promise { + const result = await this.consoleInterface.execConsoleSync('adb', { + cwd: this.returnDefaultADBPath() + }) + return result.toLocaleString().includes(this.successADBReturn) + } + + public async getDefaultADBPath() { + if (await this.hasAndroidInEnv()) { + return os.homedir() + } else if (await this.hasPlatformToolsDefaultFolder()) { + return this.returnDefaultADBPath() + } + throw new ADBNotFoundError() + } + + public async sendADBCommand(command: string): Promise { + return this.consoleInterface.execConsoleSync(command, { + cwd: await this.getDefaultADBPath() + }) + } +} + +export class ADBNotFoundError extends Error { + constructor(message = 'ADB not founded in this machine') { + super(message) + this.message = message + } +} diff --git a/src/adb-wrapper/index.ts b/src/adb-wrapper/index.ts index 864d1bf..9f94213 100644 --- a/src/adb-wrapper/index.ts +++ b/src/adb-wrapper/index.ts @@ -1,3 +1,4 @@ +import * as os from 'os' import adbCommands from './adb-commands' import { ConsoleChannel, consoleReturnAre } from '../console/console-channel' import adbReturns from './adb-returns' @@ -5,52 +6,50 @@ import adbMessages from './adb-messages' import { NetHelpers } from '../net-helpers' import { IPHelpers } from './ip-helpers' import { DeviceHelpers } from './device-helpers' +import { ADBResolver } from '../adb-resolver' +import { IConsoleInterface } from '../console/console-interface/iconsole-interface' +import { log } from 'util' -const mapIPToDeviceName = (ipAddress: string): string => { - let extractedIP = IPHelpers.extractIPRegex(ipAddress) - try { - const nameOfDevice = DeviceHelpers.getDeviceModel( - this.consoleInstance, - extractedIP - ) - return `${extractedIP} | ${nameOfDevice}` - } catch (e) { - return `${extractedIP} | NO DEVICE INFO` +export class ADBConnection extends ConsoleChannel { + private resolverInstance: ADBResolver + constructor(ciInstance: IConsoleInterface) { + super(ciInstance) + this.resolverInstance = new ADBResolver(os.homedir(), os.type(), ciInstance) } -} -export class ADBChannel extends ConsoleChannel { /** * connect to a given ip address * @param ipAddress "192.168.1.100" */ - public ConnectToDevice(ipAddress: string): ADBResult { + public async ConnectToDevice(ipAddress: string): Promise { let finalResult = null const deviceIP = IPHelpers.extractIPRegex(ipAddress) - const result = this.consoleInstance.execConsoleSync( + const result = await this.resolverInstance.sendADBCommand( adbCommands.CONNECT_IP_AND_PORT(deviceIP, '5555') ) - const output = result.toString() + const resultString = result.toString() const deviceName = DeviceHelpers.getDeviceModel( this.consoleInstance, deviceIP ) - if (consoleReturnAre(output, adbReturns.CONNECTED_TO())) { + if (consoleReturnAre(resultString, adbReturns.CONNECTED_TO())) { finalResult = new ADBResult( ADBResultState.ConnectedToDevice, `Connected to: ${deviceName}` ) } - if (consoleReturnAre(output, adbReturns.ALLREADY_CONNECTED_TO())) { + if (consoleReturnAre(resultString, adbReturns.ALLREADY_CONNECTED_TO())) { throw new ADBInterfaceException(`Allready connected to: ${deviceName}`) } - if (consoleReturnAre(output, adbReturns.CONNECTION_REFUSED(deviceIP))) { + if ( + consoleReturnAre(resultString, adbReturns.CONNECTION_REFUSED(deviceIP)) + ) { throw new ADBInterfaceException( 'Connection refused:\n Target machine actively refused connection.' ) } - if (consoleReturnAre(output, adbReturns.MISSING_PORT(deviceIP))) { + if (consoleReturnAre(resultString, adbReturns.MISSING_PORT(deviceIP))) { throw new ADBInterfaceException('Port is missing fail to connect in ADB.') } @@ -62,7 +61,7 @@ export class ADBChannel extends ConsoleChannel { public async ResetPorts(): Promise { let finalResult = null try { - const result = this.consoleInstance.execConsoleSync( + const result = this.resolverInstance.sendADBCommand( adbCommands.RESET_PORTS() ) const output = result.toString() @@ -91,7 +90,7 @@ export class ADBChannel extends ConsoleChannel { public async DisconnectFromAllDevices(): Promise { let finalResult = null try { - const result = this.consoleInstance.execConsoleSync( + const result = this.resolverInstance.sendADBCommand( adbCommands.ADB_DISCONNECT_ALL() ) const output = result.toString() @@ -112,7 +111,7 @@ export class ADBChannel extends ConsoleChannel { public async FindConnectedDevices(): Promise> { let devicesArray = [] try { - const result = this.consoleInstance.execConsoleSync( + const result = await this.resolverInstance.sendADBCommand( adbCommands.LIST_ADB_DEVICES() ) const output = result.toString() @@ -126,7 +125,19 @@ export class ADBChannel extends ConsoleChannel { } // try to get device name trought adb - ips = ips.map(mapIPToDeviceName) + ips = ips.map((ipAddress: string): string => { + let extractedIP = IPHelpers.extractIPRegex(ipAddress) + try { + const nameOfDevice = DeviceHelpers.getDeviceModel( + this.consoleInstance, + extractedIP + ) + return `${extractedIP} | ${nameOfDevice}` + } catch (e) { + return `${extractedIP} | NO DEVICE INFO` + } + }) + return ips } } catch (e) { @@ -141,16 +152,20 @@ export class ADBChannel extends ConsoleChannel { public async KillADBServer(): Promise { let returned = null try { - const result = this.consoleInstance.execConsoleSync( + const result = await this.resolverInstance.sendADBCommand( adbCommands.ADB_KILL_SERVER() ) if (result.toString() == adbReturns.ADB_KILLED_SUCCESS_RETURN()) { returned = new ADBResult(ADBResultState.Success, 'ADB Server killed') } else { - throw Error('Internal error ocurred') + throw new ADBInterfaceError('ADB Server not killed') } } catch (e) { - throw new ADBInterfaceException(e.message) + if (e instanceof ADBInterfaceError) { + throw e + } else { + throw new ADBInterfaceException(e.message) + } } if (returned == null) { throw new ADBInterfaceError('Fail during ADB Kill') @@ -187,7 +202,7 @@ export class ADBResult { export class ADBInterfaceError extends Error { AdbINterFaceError(message: string) { - this.message = adbMessages.ADB_INTERFACE_ERROR_DEFAULT() + this.message = message ?? adbMessages.ADB_INTERFACE_ERROR_DEFAULT() } } export class ADBInterfaceException extends Error { diff --git a/src/console/console-channel/index.ts b/src/console/console-channel/index.ts index 4d7b700..9d4840d 100644 --- a/src/console/console-channel/index.ts +++ b/src/console/console-channel/index.ts @@ -1,3 +1,4 @@ +import { ExecSyncOptions } from 'child_process' import { IConsoleInterface } from '../console-interface/iconsole-interface' export class ConsoleChannel { @@ -5,8 +6,11 @@ export class ConsoleChannel { constructor(CiInstance: IConsoleInterface) { this.consoleInstance = CiInstance } - sendCommandSync(consoleCommand: string): Buffer { - return this.consoleInstance.execConsoleSync(consoleCommand) + sendCommandSync( + consoleCommand: string, + options: ExecSyncOptions = null + ): Buffer { + return this.consoleInstance.execConsoleSync(consoleCommand, options) } } diff --git a/src/console/console-interface/console-interface-mock.ts b/src/console/console-interface/console-interface-mock.ts index 82c6ce8..3f45b86 100644 --- a/src/console/console-interface/console-interface-mock.ts +++ b/src/console/console-interface/console-interface-mock.ts @@ -7,13 +7,14 @@ interface ConsoleCallback { } export class ConsoleInterfaceMock implements IConsoleInterface { - private _output: Buffer + public interceptor = (input, output) => { + return output + } private _callback: ConsoleCallback private _returnStack: Array = [] public returnInfinity: boolean = true constructor() { - this._output = Buffer.from('') this._callback = null } @@ -24,12 +25,12 @@ export class ConsoleInterfaceMock implements IConsoleInterface { } pushToReturnStack(toReturn: Array | Buffer) { - if (isArray(toReturn)) { + if (toReturn instanceof Buffer) { + this._returnStack.push(toReturn) + } else { toReturn.forEach(element => { this._returnStack.push(element) }) - } else { - this._returnStack.push(toReturn) } } @@ -38,11 +39,20 @@ export class ConsoleInterfaceMock implements IConsoleInterface { } execConsoleSync(command: string): Buffer { + let toRet = Buffer.from('') + + this._callback if (this._callback != null) { - return this._callback(command) + toRet = this._callback(command) + } else { + if (this._returnStack.length == 1 && this.returnInfinity) { + toRet = this._returnStack[this._returnStack.length - 1] + } else { + toRet = this._returnStack.shift() + } } - if (this.returnInfinity) - return this._returnStack[this._returnStack.length - 1] - else return this._returnStack.shift() + if (this.interceptor) { + return this.interceptor(command, toRet) + } else return toRet } } diff --git a/src/console/console-interface/iconsole-interface.ts b/src/console/console-interface/iconsole-interface.ts index 555ca7f..e4eb815 100644 --- a/src/console/console-interface/iconsole-interface.ts +++ b/src/console/console-interface/iconsole-interface.ts @@ -1,3 +1,5 @@ +import { ExecSyncOptions } from 'child_process' + export interface IConsoleInterface { - execConsoleSync(command: string): Buffer + execConsoleSync(command: string, options?: ExecSyncOptions): Buffer } diff --git a/src/console/console-interface/index.ts b/src/console/console-interface/index.ts index 457f27c..b8b290f 100644 --- a/src/console/console-interface/index.ts +++ b/src/console/console-interface/index.ts @@ -1,8 +1,8 @@ -import { execSync } from 'child_process' +import { execSync, ExecSyncOptions } from 'child_process' import { IConsoleInterface } from './iconsole-interface' export class ConsoleInterface implements IConsoleInterface { - execConsoleSync(command: string): Buffer { - return execSync(command) + execConsoleSync(command: string, options: ExecSyncOptions = null): Buffer { + return execSync(command, options) } } diff --git a/src/extension/index.ts b/src/extension/index.ts index ad72687..6cd0de3 100644 --- a/src/extension/index.ts +++ b/src/extension/index.ts @@ -1,6 +1,6 @@ import { ADBResultState, - ADBChannel as ADBManagerChannel, + ADBConnection, ADBInterfaceException, ADBResult } from '../adb-wrapper' @@ -9,41 +9,52 @@ import * as vscode from 'vscode' import { ConsoleInterface } from '../console/console-interface' import * as appStateKeys from './global-state-keys' +import * as os from 'os' import { IPHelpers } from '../adb-wrapper/ip-helpers' +import { ADBResolver, ADBNotFoundError } from '../adb-resolver' -const cInterface = new ConsoleInterface() - -const firebaseInstance = new FirebaseManagerChannel(cInterface) -const adbInstance = new ADBManagerChannel(cInterface) - +const consoleInstance = new ConsoleInterface() +const firebaseInstance = new FirebaseManagerChannel(consoleInstance) +const adbInstance = new ADBConnection(consoleInstance) +function genericErrorReturn(e: Error) { + if (e instanceof ADBInterfaceException) { + vscode.window.showWarningMessage(e.message) + } else { + vscode.window.showErrorMessage('Error:' + e.message) + } +} export async function ResetDevicesPort(context: vscode.ExtensionContext) { - vscode.window.withProgress( - { - location: vscode.ProgressLocation.Notification, - title: 'Starting ADB' - }, - async progress => { - try { - progress.report({ message: 'Reseting ports to 5555', increment: 50 }) - let adbInterfaceResult = await adbInstance.ResetPorts() - switch (adbInterfaceResult.state) { - case ADBResultState.NoDevices: - vscode.window.showWarningMessage(adbInterfaceResult.message) - break - case ADBResultState.DevicesInPortMode: - vscode.window.showInformationMessage(adbInterfaceResult.message) - break - default: - vscode.window.showErrorMessage(adbInterfaceResult.message) - break + try { + vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: 'Starting ADB' + }, + async progress => { + try { + progress.report({ message: 'Reseting ports to 5555', increment: 50 }) + let adbInterfaceResult = await adbInstance.ResetPorts() + switch (adbInterfaceResult.state) { + case ADBResultState.NoDevices: + vscode.window.showWarningMessage(adbInterfaceResult.message) + break + case ADBResultState.DevicesInPortMode: + vscode.window.showInformationMessage(adbInterfaceResult.message) + break + default: + vscode.window.showErrorMessage(adbInterfaceResult.message) + break + } + return async () => {} + } catch (e) { + genericErrorReturn(e) } - return async () => {} - } catch (e) { - vscode.window.showErrorMessage(e.message) } - } - ) - // Display a message box to the user + ) + // Display a message box to the user + } catch (e) { + genericErrorReturn(e) + } } export async function ConnectToDevice(context: vscode.ExtensionContext) { @@ -88,11 +99,7 @@ async function connectToAdbDevice( break } } catch (e) { - if (e instanceof ADBInterfaceException) { - vscode.window.showWarningMessage(e.message) - } else { - vscode.window.showErrorMessage('Error:' + e.message) - } + genericErrorReturn(e) } } @@ -111,50 +118,60 @@ export async function DisconnectAnyDevice(context: vscode.ExtensionContext) { break } } catch (e) { - vscode.window.showErrorMessage( - 'Fail to disconnect all devices\n' + e.message - ) + genericErrorReturn(e) } } export async function KillADBServer(context: vscode.ExtensionContext) { - const adbInterfaceResult = await adbInstance.KillADBServer() - if (adbInterfaceResult.state == ADBResultState.Success) { - vscode.window.showInformationMessage(adbInterfaceResult.message) - } else { - vscode.window.showErrorMessage( - 'Fail to Kill ADB interface' + adbInterfaceResult.message - ) + try { + const adbInterfaceResult = await adbInstance.KillADBServer() + if (adbInterfaceResult.state == ADBResultState.Success) { + vscode.window.showInformationMessage(adbInterfaceResult.message) + } else { + vscode.window.showErrorMessage( + 'Fail to Kill ADB interface' + adbInterfaceResult.message + ) + } + } catch (e) { + genericErrorReturn(e) } } export async function ConnectToDeviceFromList( context: vscode.ExtensionContext ) { - const ipAddresses = await getIPAddressList(context) - const ipSelected = await vscode.window.showQuickPick(ipAddresses, { - ignoreFocusOut: true, - placeHolder: 'Select the IP address of the device to connect to...' - }) - if (ipSelected == null) { - vscode.window.showErrorMessage('Device IP Address not selected.') - } else { - // wait disconnect from adb device - await adbInstance.DisconnectFromAllDevices() - await connectToAdbDevice(context, IPHelpers.extractIPRegex(ipSelected)) + try { + const ipAddresses = await getIPAddressList(context) + const ipSelected = await vscode.window.showQuickPick(ipAddresses, { + ignoreFocusOut: true, + placeHolder: 'Select the IP address of the device to connect to...' + }) + if (ipSelected == null) { + throw new Error('Device IP Address not selected.') + } else { + // wait disconnect from adb device + await adbInstance.DisconnectFromAllDevices() + await connectToAdbDevice(context, IPHelpers.extractIPRegex(ipSelected)) + } + } catch (error) { + genericErrorReturn(error) } } async function getIPAddressList(context) { - const connectedDevices = await adbInstance.FindConnectedDevices() - const lastIPSelected = await context.globalState.get( - appStateKeys.lastIPUsed, - '' - ) - if (lastIPSelected != null && lastIPSelected != '') { - // add last selected ip to begining of array - connectedDevices.unshift(lastIPSelected) + try { + const connectedDevices = await adbInstance.FindConnectedDevices() + const lastIPSelected = await context.globalState.get( + appStateKeys.lastIPUsed, + '' + ) + if (lastIPSelected != null && lastIPSelected != '') { + // add last selected ip to begining of array + connectedDevices.unshift(lastIPSelected) + } + return connectedDevices + } catch (e) { + genericErrorReturn(e) } - return connectedDevices } export async function EnableFirebaseDebugView( context: vscode.ExtensionContext @@ -190,7 +207,7 @@ export async function EnableFirebaseDebugView( break } } catch (e) { - vscode.window.showErrorMessage('Fail to connect to device \n' + e.message) + genericErrorReturn(e) } } @@ -210,6 +227,6 @@ export async function DisableFirebaseDebugView( break } } catch (e) { - vscode.window.showErrorMessage('Fail to connect to device \n' + e.message) + genericErrorReturn(e) } }