@@ -30,18 +30,40 @@ import {
30
30
isFlutterDriverCommand ,
31
31
waitForFlutterServerToBeActive ,
32
32
} from './utils' ;
33
- import { util } from 'appium/support' ;
33
+ import { logger , util } from 'appium/support' ;
34
34
import { androidPortForward , androidRemovePortForward } from './android' ;
35
35
import { iosPortForward , iosRemovePortForward } from './iOS' ;
36
36
import type { PortForwardCallback , PortReleaseCallback } from './types' ;
37
37
import _ from 'lodash' ;
38
38
39
+ import type {
40
+ RouteMatcher
41
+ } from '@appium/types' ;
42
+
43
+ const WEBVIEW_NO_PROXY = [
44
+ [ `GET` , new RegExp ( `^/session/[^/]+/appium` ) ] ,
45
+ [ `GET` , new RegExp ( `^/session/[^/]+/context` ) ] ,
46
+ [ `GET` , new RegExp ( `^/session/[^/]+/element/[^/]+/rect` ) ] ,
47
+ [ `GET` , new RegExp ( `^/session/[^/]+/log/types$` ) ] ,
48
+ [ `GET` , new RegExp ( `^/session/[^/]+/orientation` ) ] ,
49
+ [ `POST` , new RegExp ( `^/session/[^/]+/appium` ) ] ,
50
+ [ `POST` , new RegExp ( `^/session/[^/]+/context` ) ] ,
51
+ [ `POST` , new RegExp ( `^/session/[^/]+/log$` ) ] ,
52
+ [ `POST` , new RegExp ( `^/session/[^/]+/orientation` ) ] ,
53
+ [ `POST` , new RegExp ( `^/session/[^/]+/touch/multi/perform` ) ] ,
54
+ [ `POST` , new RegExp ( `^/session/[^/]+/touch/perform` ) ] ,
55
+ ] as import ( '@appium/types' ) . RouteMatcher [ ] ;
56
+
57
+
39
58
export class AppiumFlutterDriver extends BaseDriver < FlutterDriverConstraints > {
40
59
// @ts -ignore
41
60
public proxydriver : XCUITestDriver | AndroidUiautomator2Driver ;
42
61
public flutterPort : number | null | undefined ;
43
62
private internalCaps : DriverCaps < FlutterDriverConstraints > | undefined ;
44
63
public proxy : JWProxy | undefined ;
64
+ private proxyWebViewActive : boolean = false ;
65
+ public readonly NATIVE_CONTEXT_NAME : string = `NATIVE_APP` ;
66
+ public currentContext : string = this . NATIVE_CONTEXT_NAME ;
45
67
click = click ;
46
68
findElOrEls = findElOrEls ;
47
69
getText = getText ;
@@ -193,12 +215,31 @@ export class AppiumFlutterDriver extends BaseDriver<FlutterDriverConstraints> {
193
215
}
194
216
195
217
async executeCommand ( command : any , ...args : any ) {
196
- if ( isFlutterDriverCommand ( command ) ) {
218
+ if ( this . currentContext === this . NATIVE_CONTEXT_NAME && isFlutterDriverCommand ( command ) ) {
197
219
return await super . executeCommand ( command , ...args ) ;
198
220
}
221
+
222
+ this . handleContextSwitch ( command , args ) ;
223
+ logger . default . info ( `Executing the proxy command: ${ command } with args: ${ args } ` ) ;
199
224
return await this . proxydriver . executeCommand ( command as string , ...args ) ;
200
225
}
201
226
227
+ private handleContextSwitch ( command : string , args : any [ ] ) : void {
228
+ if ( command === 'setContext' ) {
229
+ const isWebviewContext = args . find ( ( arg ) => typeof arg === 'string' && arg . includes ( 'WEBVIEW' ) ) ;
230
+ this . currentContext = args [ 0 ] ;
231
+ if ( isWebviewContext ) {
232
+ this . proxyWebViewActive = true ;
233
+ } else {
234
+ this . proxyWebViewActive = false ;
235
+ }
236
+ }
237
+ }
238
+
239
+ public getProxyAvoidList ( ) : RouteMatcher [ ] {
240
+ return WEBVIEW_NO_PROXY ;
241
+ }
242
+
202
243
public async createSession (
203
244
...args : any [ ]
204
245
) : Promise < DefaultCreateSessionResult < FlutterDriverConstraints > > {
@@ -382,8 +423,20 @@ export class AppiumFlutterDriver extends BaseDriver<FlutterDriverConstraints> {
382
423
return await this . proxydriver . execute ( script , args ) ;
383
424
}
384
425
385
- canProxy ( ) {
386
- return false ;
426
+ public proxyActive ( ) : boolean {
427
+ // In WebView context, all request should got to each driver
428
+ // so that they can handle http request properly.
429
+ // On iOS, WebView context is handled by XCUITest driver while Android is by chromedriver.
430
+ // It means XCUITest driver should keep the XCUITest driver as a proxy,
431
+ // while UIAutomator2 driver should proxy to chromedriver instead of UIA2 proxy.
432
+ return (
433
+ this . proxyWebViewActive &&
434
+ this . proxydriver . constructor . name !== XCUITestDriver . name
435
+ ) ;
436
+ }
437
+
438
+ public canProxy ( ) : boolean {
439
+ return this . proxyWebViewActive ;
387
440
}
388
441
389
442
async deleteSession ( ) {
@@ -400,6 +453,8 @@ export class AppiumFlutterDriver extends BaseDriver<FlutterDriverConstraints> {
400
453
401
454
async mobilelaunchApp ( appId : string , args : string [ ] , environment : any ) {
402
455
let activateAppResponse ;
456
+ this . currentContext = this . NATIVE_CONTEXT_NAME ;
457
+ this . proxyWebViewActive = false ;
403
458
const launchArgs = _ . assign (
404
459
{ arguments : [ ] as string [ ] } ,
405
460
{ arguments : args , environment } ,
0 commit comments