11import ADB from 'appium-adb' ;
22import { Proxy , ProxyOptions } from '../proxy' ;
3+ import logger from '../logger' ;
34
45export type ADBInstance = ADB ;
56export type UDID = string ;
@@ -25,17 +26,42 @@ export async function isRealDevice(adb: ADBInstance, udid: UDID): Promise<boolea
2526 return property !== 'emulator' ;
2627}
2728
29+ /**
30+ * Configures the global HTTP proxy settings for Wi-Fi traffic on the target Android device via ADB.
31+ * If a valid proxy configuration is provided:
32+ * 1. It sets up an 'adb reverse' tunnel for real devices to ensure the device can reach the host-side proxy.
33+ * 2. It sets the 'http_proxy' global setting to 'IP:PORT'.
34+ * If the configuration is invalid or missing, it sets the 'http_proxy' to ':0' (which disables the proxy).
35+ *
36+ * @param adb - The ADB instance established by Appium.
37+ * @param udid - The Unique Device Identifier (UDID) of the Android device or emulator.
38+ * @param isRealDevice - Boolean indicating if the target is a physical device (requires adb reverse).
39+ * @param proxyConfig - Optional configuration object containing the IP and port for the proxy.
40+ * @returns A Promise resolving to the output of the final ADB shell command.
41+ * @throws {Error } Throws an error if any ADB command execution fails.
42+ */
2843export async function configureWifiProxy (
2944 adb : ADBInstance ,
3045 udid : UDID ,
31- realDevice : boolean ,
32- proxy ?: ProxyOptions
46+ isRealDevice : boolean ,
47+ proxyConfig ?: ProxyOptions
3348) : Promise < string > {
49+ logger . info ( `configureWifiProxy(udid=${ udid } , isRealDevice=${ isRealDevice } , proxyConfig=${ JSON . stringify ( proxyConfig ) } )` )
3450 try {
35- const host = proxy ? `${ proxy . ip } :${ proxy . port } ` : ':0' ;
51+ const isConfigValid = proxyConfig
52+ && proxyConfig . ip
53+ && proxyConfig . ip . trim ( ) . length > 0
54+ && ! isNaN ( proxyConfig . port )
55+ && proxyConfig . port > 0 ;
3656
37- if ( realDevice && proxy ) {
38- await adbExecWithDevice ( adb , udid , [ 'reverse' , `tcp:${ proxy . port } ` , `tcp:${ proxy . port } ` ] ) ;
57+ if ( ! isConfigValid ) {
58+ logger . warn ( `Invalid proxy config: ${ JSON . stringify ( proxyConfig ) } . Proxy will be disabled for udid ${ udid } .` ) ;
59+ }
60+
61+ const host = isConfigValid ? `${ proxyConfig . ip } :${ proxyConfig . port } ` : ':0' ;
62+
63+ if ( isRealDevice && isConfigValid ) {
64+ await adbExecWithDevice ( adb , udid , [ 'reverse' , `tcp:${ proxyConfig . port } ` , `tcp:${ proxyConfig . port } ` ] ) ;
3965 }
4066
4167 return await adbExecWithDevice ( adb , udid , [
@@ -51,36 +77,66 @@ export async function configureWifiProxy(
5177 }
5278}
5379
54- export async function getGlobalProxyValue (
80+ /**
81+ * Retrieves the current global HTTP proxy settings from the target Android device via ADB.
82+ * The function checks the 'http_proxy' setting in the 'global' namespace of the Android system settings.
83+ *
84+ * @param adb - The ADB instance established by Appium.
85+ * @param udid - The Unique Device Identifier (UDID) of the Android device or emulator.
86+ * @returns A Promise resolving to an object containing the IP and port of the proxy
87+ * ({ ip: string, port: number }), or undefined if no proxy is configured,
88+ * or if the configuration is invalid (e.g., malformed port).
89+ * @throws {Error } Throws an error if the ADB command execution fails.
90+ */
91+ export async function getCurrentWifiProxyConfig (
5592 adb : ADBInstance ,
5693 udid : UDID
57- ) : Promise < ProxyOptions > {
94+ ) : Promise < ProxyOptions | undefined > {
95+ logger . info ( `getCurrentWifiProxyConfig(udid=${ udid } )` ) ;
5896 try {
59- const proxy = await adbExecWithDevice ( adb , udid , [
97+ // Execute ADB command to get the current global HTTP proxy setting
98+ const proxySettingsCommandResult = await adbExecWithDevice ( adb , udid , [
6099 'shell' ,
61100 'settings' ,
62101 'get' ,
63102 'global' ,
64- 'http_proxy'
65- ] )
103+ 'http_proxy' ,
104+ ] ) ;
66105
67- if ( proxy == ":0" || proxy == "null" ) {
68- return {
69- port : 0
70- } as ProxyOptions
106+ // ADB returns ":0" or "null" when the proxy is disabled.
107+ if ( ! proxySettingsCommandResult || proxySettingsCommandResult === ':0' || proxySettingsCommandResult === 'null' ) {
108+ logger . info ( `No active proxy for udid ${ udid } .` ) ;
109+ return undefined ;
71110 }
72111
73- const [ ip , portStr ] = proxy . split ( ":" ) ;
112+ // Ensure the format is IP:PORT (must contain at least one ':').
113+ if ( ! proxySettingsCommandResult . includes ( ':' ) ) {
114+ logger . warn ( `Invalid proxy settings format detected for udid ${ udid } : '${ proxySettingsCommandResult } '.` ) ;
115+ return undefined ;
116+ }
117+
118+ // Split the string into IP and port
119+ const [ ip , portStr ] = proxySettingsCommandResult . split ( ':' , 2 ) ;
74120 const port = Number ( portStr ) ;
75121
76- return {
77- ip : ip ,
78- port : port
79- } as ProxyOptions
122+ // Validate IP and port values.
123+ // IP should not be empty after trimming, and port must be a valid number greater than 0.
124+ if ( ! ip . trim ( ) || isNaN ( port ) || port <= 0 ) {
125+ logger . warn ( `Invalid proxy settings detected for udid ${ udid } : (ip=${ ip } , port=${ port } )` ) ;
126+ return undefined ;
127+ }
128+
129+ const proxyOptions : ProxyOptions = {
130+ ip : ip . trim ( ) ,
131+ port : port ,
132+ } as ProxyOptions ;
133+
134+ logger . info ( `Found active proxy for udid ${ udid } : ${ JSON . stringify ( proxyOptions ) } ` ) ;
135+ return proxyOptions ;
80136
81137 } catch ( error : any ) {
82- throw new Error ( `Error get global proxy value ${ udid } : ${ error . message } ` ) ;
83- }
138+ throw new Error ( `Error getting wifi proxy settings for ${ udid } : ${ error . message } ` ) ;
139+ }
84140}
85141
86142/**
0 commit comments