Skip to content

Commit f984604

Browse files
author
Tim Wang
committed
feat: enable webview context handling and command proxying in driver
1 parent c9a3422 commit f984604

File tree

1 file changed

+59
-4
lines changed

1 file changed

+59
-4
lines changed

src/driver.ts

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,40 @@ import {
3030
isFlutterDriverCommand,
3131
waitForFlutterServerToBeActive,
3232
} from './utils';
33-
import { util } from 'appium/support';
33+
import { logger, util } from 'appium/support';
3434
import { androidPortForward, androidRemovePortForward } from './android';
3535
import { iosPortForward, iosRemovePortForward } from './iOS';
3636
import type { PortForwardCallback, PortReleaseCallback } from './types';
3737
import _ from 'lodash';
3838

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+
3958
export class AppiumFlutterDriver extends BaseDriver<FlutterDriverConstraints> {
4059
// @ts-ignore
4160
public proxydriver: XCUITestDriver | AndroidUiautomator2Driver;
4261
public flutterPort: number | null | undefined;
4362
private internalCaps: DriverCaps<FlutterDriverConstraints> | undefined;
4463
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;
4567
click = click;
4668
findElOrEls = findElOrEls;
4769
getText = getText;
@@ -193,12 +215,31 @@ export class AppiumFlutterDriver extends BaseDriver<FlutterDriverConstraints> {
193215
}
194216

195217
async executeCommand(command: any, ...args: any) {
196-
if (isFlutterDriverCommand(command)) {
218+
if (this.currentContext === this.NATIVE_CONTEXT_NAME && isFlutterDriverCommand(command)) {
197219
return await super.executeCommand(command, ...args);
198220
}
221+
222+
this.handleContextSwitch(command, args);
223+
logger.default.info(`Executing the proxy command: ${command} with args: ${args}`);
199224
return await this.proxydriver.executeCommand(command as string, ...args);
200225
}
201226

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+
202243
public async createSession(
203244
...args: any[]
204245
): Promise<DefaultCreateSessionResult<FlutterDriverConstraints>> {
@@ -382,8 +423,20 @@ export class AppiumFlutterDriver extends BaseDriver<FlutterDriverConstraints> {
382423
return await this.proxydriver.execute(script, args);
383424
}
384425

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;
387440
}
388441

389442
async deleteSession() {
@@ -400,6 +453,8 @@ export class AppiumFlutterDriver extends BaseDriver<FlutterDriverConstraints> {
400453

401454
async mobilelaunchApp(appId: string, args: string[], environment: any) {
402455
let activateAppResponse;
456+
this.currentContext = this.NATIVE_CONTEXT_NAME;
457+
this.proxyWebViewActive = false;
403458
const launchArgs = _.assign(
404459
{ arguments: [] as string[] },
405460
{ arguments: args, environment },

0 commit comments

Comments
 (0)