Skip to content

Commit 0abd6e3

Browse files
authored
feat: implement webinspector shim service (#81)
1 parent 5e3762c commit 0abd6e3

File tree

8 files changed

+853
-0
lines changed

8 files changed

+853
-0
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"test:image-mounter": "mocha test/integration/mobile-image-mounter-test.ts --exit --timeout 1m",
3333
"test:mobile-config": "mocha test/integration/mobile-config-test.ts --exit --timeout 1m",
3434
"test:springboard": "mocha test/integration/springboard-service-test.ts --exit --timeout 1m",
35+
"test:webinspector": "mocha test/integration/webinspector-test.ts --exit --timeout 1m",
3536
"test:unit": "mocha 'test/unit/**/*.ts' --exit --timeout 2m",
3637
"test:tunnel-creation": "sudo tsx scripts/test-tunnel-creation.ts",
3738
"test:tunnel-creation:lsof": "sudo tsx scripts/test-tunnel-creation.ts --keep-open"

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export type {
1818
NotificationProxyService,
1919
MobileConfigService,
2020
SpringboardService,
21+
WebInspectorService,
2122
SyslogService,
2223
SocketInfo,
2324
TunnelResult,
@@ -28,6 +29,7 @@ export type {
2829
NotificationProxyServiceWithConnection,
2930
MobileConfigServiceWithConnection,
3031
SpringboardServiceWithConnection,
32+
WebInspectorServiceWithConnection,
3133
} from './lib/types.js';
3234
export {
3335
createUsbmux,

src/lib/types.ts

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,121 @@ export interface MobileConfigServiceWithConnection {
312312
remoteXPC: RemoteXpcConnection;
313313
}
314314

315+
/**
316+
* Represents the WebInspectorService
317+
*/
318+
export interface WebInspectorService extends BaseService {
319+
/**
320+
* Send a message to the WebInspector service
321+
* @param selector The RPC selector (e.g., '_rpc_reportIdentifier:')
322+
* @param args The arguments dictionary for the message
323+
* @returns Promise that resolves when the message is sent
324+
*/
325+
sendMessage(selector: string, args?: PlistDictionary): Promise<void>;
326+
327+
/**
328+
* Listen to messages from the WebInspector service using async generator
329+
* @yields PlistMessage - Messages received from the WebInspector service
330+
*/
331+
listenMessage(): AsyncGenerator<PlistMessage, void, unknown>;
332+
333+
/**
334+
* Stop listening to messages
335+
*/
336+
stopListening(): void;
337+
338+
/**
339+
* Close the connection and clean up resources
340+
*/
341+
close(): Promise<void>;
342+
343+
/**
344+
* Get the connection ID being used for this service
345+
* @returns The connection identifier
346+
*/
347+
getConnectionId(): string;
348+
349+
/**
350+
* Request application launch
351+
* @param bundleId The bundle identifier of the application to launch
352+
*/
353+
requestApplicationLaunch(bundleId: string): Promise<void>;
354+
355+
/**
356+
* Get connected applications
357+
*/
358+
getConnectedApplications(): Promise<void>;
359+
360+
/**
361+
* Forward get listing for an application
362+
* @param appId The application identifier
363+
*/
364+
forwardGetListing(appId: string): Promise<void>;
365+
366+
/**
367+
* Forward automation session request
368+
* @param sessionId The session identifier
369+
* @param appId The application identifier
370+
* @param capabilities Optional session capabilities
371+
*/
372+
forwardAutomationSessionRequest(
373+
sessionId: string,
374+
appId: string,
375+
capabilities?: PlistDictionary,
376+
): Promise<void>;
377+
378+
/**
379+
* Forward socket setup for inspector connection
380+
* @param sessionId The session identifier
381+
* @param appId The application identifier
382+
* @param pageId The page identifier
383+
* @param automaticallyPause Whether to automatically pause (defaults to true)
384+
*/
385+
forwardSocketSetup(
386+
sessionId: string,
387+
appId: string,
388+
pageId: number,
389+
automaticallyPause?: boolean,
390+
): Promise<void>;
391+
392+
/**
393+
* Forward socket data to a page
394+
* @param sessionId The session identifier
395+
* @param appId The application identifier
396+
* @param pageId The page identifier
397+
* @param data The data to send (will be JSON stringified)
398+
*/
399+
forwardSocketData(
400+
sessionId: string,
401+
appId: string,
402+
pageId: number,
403+
data: any,
404+
): Promise<void>;
405+
406+
/**
407+
* Forward indicate web view
408+
* @param appId The application identifier
409+
* @param pageId The page identifier
410+
* @param enable Whether to enable indication
411+
*/
412+
forwardIndicateWebView(
413+
appId: string,
414+
pageId: number,
415+
enable: boolean,
416+
): Promise<void>;
417+
}
418+
419+
/**
420+
* Represents a WebInspectorService instance with its associated RemoteXPC connection
421+
* This allows callers to properly manage the connection lifecycle
422+
*/
423+
export interface WebInspectorServiceWithConnection {
424+
/** The WebInspectorService instance */
425+
webInspectorService: WebInspectorService;
426+
/** The RemoteXPC connection that can be used to close the connection */
427+
remoteXPC: RemoteXpcConnection;
428+
}
429+
315430
/**
316431
* Options for configuring syslog capture
317432
*/

src/service-connection.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@ export class ServiceConnection extends BasePlistService {
6060
return this.sendAndReceive(requestObj, timeout);
6161
}
6262

63+
/**
64+
* Sends a plist message without waiting for a response
65+
* This is useful for fire-and-forget style communication
66+
* @param message The message to send
67+
*/
68+
sendPlist(message: PlistDictionary): void {
69+
this.send(message);
70+
}
71+
6372
/**
6473
* Gets the underlying socket
6574
* @returns The socket used by this service

src/services.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ import type {
1010
NotificationProxyServiceWithConnection,
1111
SpringboardServiceWithConnection,
1212
SyslogService as SyslogServiceType,
13+
WebInspectorServiceWithConnection,
1314
} from './lib/types.js';
1415
import DiagnosticsService from './services/ios/diagnostic-service/index.js';
1516
import { MobileConfigService } from './services/ios/mobile-config/index.js';
1617
import MobileImageMounterService from './services/ios/mobile-image-mounter/index.js';
1718
import { NotificationProxyService } from './services/ios/notification-proxy/index.js';
1819
import { SpringBoardService } from './services/ios/springboard-service/index.js';
1920
import SyslogService from './services/ios/syslog-service/index.js';
21+
import { WebInspectorService } from './services/ios/webinspector/index.js';
2022

2123
const APPIUM_XCUITEST_DRIVER_NAME = 'appium-xcuitest-driver';
2224
const TUNNEL_REGISTRY_PORT = 'tunnelRegistryPort';
@@ -107,6 +109,22 @@ export async function startSyslogService(
107109
return new SyslogService([tunnelConnection.host, tunnelConnection.port]);
108110
}
109111

112+
export async function startWebInspectorService(
113+
udid: string,
114+
): Promise<WebInspectorServiceWithConnection> {
115+
const { remoteXPC, tunnelConnection } = await createRemoteXPCConnection(udid);
116+
const webInspectorService = remoteXPC.findService(
117+
WebInspectorService.RSD_SERVICE_NAME,
118+
);
119+
return {
120+
remoteXPC: remoteXPC as RemoteXpcConnection,
121+
webInspectorService: new WebInspectorService([
122+
tunnelConnection.host,
123+
parseInt(webInspectorService.port, 10),
124+
]),
125+
};
126+
}
127+
110128
export async function createRemoteXPCConnection(udid: string) {
111129
const tunnelConnection = await getTunnelInformation(udid);
112130
const remoteXPC = await startService(

src/services/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ import * as diagnostics from './ios/diagnostic-service/index.js';
66
import * as mobileImageMounter from './ios/mobile-image-mounter/index.js';
77
import * as syslog from './ios/syslog-service/index.js';
88
import * as tunnel from './ios/tunnel-service/index.js';
9+
import * as webinspector from './ios/webinspector/index.js';
910

1011
export {
1112
diagnostics,
1213
mobileImageMounter,
1314
syslog,
1415
tunnel,
16+
webinspector,
1517
TunnelRegistryServer,
1618
startTunnelRegistryServer,
1719
};

0 commit comments

Comments
 (0)