appium-ios-remotexpc 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/build/src/index.d.ts +2 -1
- package/build/src/index.d.ts.map +1 -1
- package/build/src/index.js +1 -0
- package/build/src/lib/types.d.ts +114 -0
- package/build/src/lib/types.d.ts.map +1 -1
- package/build/src/lib/types.js +2 -0
- package/build/src/service-connection.d.ts +6 -0
- package/build/src/service-connection.d.ts.map +1 -1
- package/build/src/service-connection.js +8 -0
- package/build/src/services/index.d.ts +3 -1
- package/build/src/services/index.d.ts.map +1 -1
- package/build/src/services/index.js +3 -1
- package/build/src/services/ios/power-assertion/index.d.ts +40 -0
- package/build/src/services/ios/power-assertion/index.d.ts.map +1 -0
- package/build/src/services/ios/power-assertion/index.js +64 -0
- package/build/src/services/ios/webinspector/index.d.ts +114 -0
- package/build/src/services/ios/webinspector/index.d.ts.map +1 -0
- package/build/src/services/ios/webinspector/index.js +286 -0
- package/build/src/services.d.ts +3 -1
- package/build/src/services.d.ts.map +1 -1
- package/build/src/services.js +24 -0
- package/package.json +3 -1
- package/src/index.ts +6 -0
- package/src/lib/types.ts +149 -0
- package/src/service-connection.ts +9 -0
- package/src/services/index.ts +4 -0
- package/src/services/ios/power-assertion/index.ts +100 -0
- package/src/services/ios/webinspector/index.ts +372 -0
- package/src/services.ts +36 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { logger } from '@appium/support';
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
PlistDictionary,
|
|
5
|
+
PowerAssertionService as PowerAssertionServiceInterface,
|
|
6
|
+
} from '../../../lib/types.js';
|
|
7
|
+
import { ServiceConnection } from '../../../service-connection.js';
|
|
8
|
+
import { BaseService } from '../base-service.js';
|
|
9
|
+
|
|
10
|
+
const log = logger.getLogger('PowerAssertionService');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Power assertion types that can be used to prevent system sleep
|
|
14
|
+
*/
|
|
15
|
+
export enum PowerAssertionType {
|
|
16
|
+
WIRELESS_SYNC = 'AMDPowerAssertionTypeWirelessSync',
|
|
17
|
+
PREVENT_USER_IDLE_SYSTEM_SLEEP = 'PreventUserIdleSystemSleep',
|
|
18
|
+
PREVENT_SYSTEM_SLEEP = 'PreventSystemSleep',
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Options for power assertion creation
|
|
23
|
+
*/
|
|
24
|
+
export interface PowerAssertionOptions {
|
|
25
|
+
type: PowerAssertionType;
|
|
26
|
+
name: string;
|
|
27
|
+
timeout: number; // timeout in seconds
|
|
28
|
+
details?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* PowerAssertionService provides an API to create power assertions.
|
|
33
|
+
*/
|
|
34
|
+
class PowerAssertionService
|
|
35
|
+
extends BaseService
|
|
36
|
+
implements PowerAssertionServiceInterface
|
|
37
|
+
{
|
|
38
|
+
static readonly RSD_SERVICE_NAME =
|
|
39
|
+
'com.apple.mobile.assertion_agent.shim.remote';
|
|
40
|
+
|
|
41
|
+
private _conn: ServiceConnection | null = null;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Create a power assertion to prevent system sleep
|
|
45
|
+
* @param options Options for creating the power assertion
|
|
46
|
+
* @returns Promise that resolves when the assertion is created
|
|
47
|
+
*/
|
|
48
|
+
async createPowerAssertion(options: PowerAssertionOptions): Promise<void> {
|
|
49
|
+
if (!this._conn) {
|
|
50
|
+
this._conn = await this.connectToPowerAssertionService();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const request = this.buildCreateAssertionRequest(options);
|
|
54
|
+
await this._conn.sendPlistRequest(request);
|
|
55
|
+
log.info(
|
|
56
|
+
`Power assertion created: type="${options.type}", name="${options.name}", timeout=${options.timeout}s`,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Close the connection to the power assertion service
|
|
62
|
+
*/
|
|
63
|
+
async close(): Promise<void> {
|
|
64
|
+
if (this._conn) {
|
|
65
|
+
await this._conn.close();
|
|
66
|
+
this._conn = null;
|
|
67
|
+
log.debug('Power assertion service connection closed');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private async connectToPowerAssertionService(): Promise<ServiceConnection> {
|
|
72
|
+
const service = {
|
|
73
|
+
serviceName: PowerAssertionService.RSD_SERVICE_NAME,
|
|
74
|
+
port: this.address[1].toString(),
|
|
75
|
+
};
|
|
76
|
+
log.debug(
|
|
77
|
+
`Connecting to power assertion service at ${this.address[0]}:${this.address[1]}`,
|
|
78
|
+
);
|
|
79
|
+
return await this.startLockdownService(service);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private buildCreateAssertionRequest(
|
|
83
|
+
options: PowerAssertionOptions,
|
|
84
|
+
): PlistDictionary {
|
|
85
|
+
const request: PlistDictionary = {
|
|
86
|
+
CommandKey: 'CommandCreateAssertion',
|
|
87
|
+
AssertionTypeKey: options.type,
|
|
88
|
+
AssertionNameKey: options.name,
|
|
89
|
+
AssertionTimeoutKey: options.timeout,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
if (options.details !== undefined) {
|
|
93
|
+
request.AssertionDetailKey = options.details;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return request;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export { PowerAssertionService };
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
import { logger } from '@appium/support';
|
|
2
|
+
import { randomUUID } from 'crypto';
|
|
3
|
+
import { EventEmitter } from 'events';
|
|
4
|
+
|
|
5
|
+
import type { PlistDictionary, PlistMessage } from '../../../lib/types.js';
|
|
6
|
+
import { ServiceConnection } from '../../../service-connection.js';
|
|
7
|
+
import { BaseService } from '../base-service.js';
|
|
8
|
+
|
|
9
|
+
const log = logger.getLogger('WebInspectorService');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Interface for WebInspector message structure
|
|
13
|
+
*/
|
|
14
|
+
export interface WebInspectorMessage extends PlistDictionary {
|
|
15
|
+
__selector: string;
|
|
16
|
+
__argument: PlistDictionary;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* WebInspectorService provides an API to:
|
|
21
|
+
* - Send messages to webinspectord
|
|
22
|
+
* - Listen to messages from webinspectord
|
|
23
|
+
* - Communicate with web views and Safari on iOS devices
|
|
24
|
+
*
|
|
25
|
+
* This service is used for web automation, inspection, and debugging.
|
|
26
|
+
*/
|
|
27
|
+
export class WebInspectorService extends BaseService {
|
|
28
|
+
static readonly RSD_SERVICE_NAME = 'com.apple.webinspector.shim.remote';
|
|
29
|
+
|
|
30
|
+
// RPC method selectors
|
|
31
|
+
private static readonly RPC_REPORT_IDENTIFIER = '_rpc_reportIdentifier:';
|
|
32
|
+
private static readonly RPC_REQUEST_APPLICATION_LAUNCH =
|
|
33
|
+
'_rpc_requestApplicationLaunch:';
|
|
34
|
+
private static readonly RPC_GET_CONNECTED_APPLICATIONS =
|
|
35
|
+
'_rpc_getConnectedApplications:';
|
|
36
|
+
private static readonly RPC_FORWARD_GET_LISTING = '_rpc_forwardGetListing:';
|
|
37
|
+
private static readonly RPC_FORWARD_AUTOMATION_SESSION_REQUEST =
|
|
38
|
+
'_rpc_forwardAutomationSessionRequest:';
|
|
39
|
+
private static readonly RPC_FORWARD_SOCKET_SETUP = '_rpc_forwardSocketSetup:';
|
|
40
|
+
private static readonly RPC_FORWARD_SOCKET_DATA = '_rpc_forwardSocketData:';
|
|
41
|
+
private static readonly RPC_FORWARD_INDICATE_WEB_VIEW =
|
|
42
|
+
'_rpc_forwardIndicateWebView:';
|
|
43
|
+
|
|
44
|
+
private connection: ServiceConnection | null = null;
|
|
45
|
+
private messageEmitter: EventEmitter = new EventEmitter();
|
|
46
|
+
private isReceiving: boolean = false;
|
|
47
|
+
private readonly connectionId: string;
|
|
48
|
+
private receivePromise: Promise<void> | null = null;
|
|
49
|
+
|
|
50
|
+
constructor(address: [string, number]) {
|
|
51
|
+
super(address);
|
|
52
|
+
this.connectionId = randomUUID().toUpperCase();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Send a message to the WebInspector service
|
|
57
|
+
* @param selector The RPC selector (e.g., '_rpc_reportIdentifier:')
|
|
58
|
+
* @param args The arguments dictionary for the message
|
|
59
|
+
* @returns Promise that resolves when the message is sent
|
|
60
|
+
*/
|
|
61
|
+
async sendMessage(
|
|
62
|
+
selector: string,
|
|
63
|
+
args: PlistDictionary = {},
|
|
64
|
+
): Promise<void> {
|
|
65
|
+
const connection = await this.connectToWebInspectorService();
|
|
66
|
+
|
|
67
|
+
// Add connection identifier to all messages
|
|
68
|
+
const message: WebInspectorMessage = {
|
|
69
|
+
__selector: selector,
|
|
70
|
+
__argument: {
|
|
71
|
+
...args,
|
|
72
|
+
WIRConnectionIdentifierKey: this.connectionId,
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
log.debug(`Sending WebInspector message: ${selector}`);
|
|
77
|
+
|
|
78
|
+
connection.sendPlist(message);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Listen to messages from the WebInspector service using async generator
|
|
83
|
+
* @yields PlistMessage - Messages received from the WebInspector service
|
|
84
|
+
*/
|
|
85
|
+
async *listenMessage(): AsyncGenerator<PlistMessage, void, unknown> {
|
|
86
|
+
await this.connectToWebInspectorService();
|
|
87
|
+
|
|
88
|
+
// Start receiving messages in background if not already started
|
|
89
|
+
if (!this.isReceiving) {
|
|
90
|
+
this.startMessageReceiver();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const queue: PlistMessage[] = [];
|
|
94
|
+
let resolveNext: ((value: IteratorResult<PlistMessage>) => void) | null =
|
|
95
|
+
null;
|
|
96
|
+
let stopped = false;
|
|
97
|
+
|
|
98
|
+
const messageHandler = (message: PlistMessage) => {
|
|
99
|
+
if (resolveNext) {
|
|
100
|
+
resolveNext({ value: message, done: false });
|
|
101
|
+
resolveNext = null;
|
|
102
|
+
} else {
|
|
103
|
+
queue.push(message);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const stopHandler = () => {
|
|
108
|
+
stopped = true;
|
|
109
|
+
if (resolveNext) {
|
|
110
|
+
resolveNext({ value: undefined, done: true });
|
|
111
|
+
resolveNext = null;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
this.messageEmitter.on('message', messageHandler);
|
|
116
|
+
this.messageEmitter.once('stop', stopHandler);
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
while (!stopped) {
|
|
120
|
+
if (queue.length > 0) {
|
|
121
|
+
yield queue.shift()!;
|
|
122
|
+
} else {
|
|
123
|
+
const message = await new Promise<PlistMessage | null>((resolve) => {
|
|
124
|
+
if (stopped) {
|
|
125
|
+
resolve(null);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
resolveNext = (result) => {
|
|
129
|
+
resolve(result.done ? null : result.value);
|
|
130
|
+
};
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
if (message === null) {
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
yield message;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
} finally {
|
|
141
|
+
this.messageEmitter.off('message', messageHandler);
|
|
142
|
+
this.messageEmitter.off('stop', stopHandler);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Stop listening to messages
|
|
148
|
+
*/
|
|
149
|
+
stopListening(): void {
|
|
150
|
+
this.isReceiving = false;
|
|
151
|
+
this.messageEmitter.emit('stop');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Close the connection and clean up resources
|
|
156
|
+
*/
|
|
157
|
+
async close(): Promise<void> {
|
|
158
|
+
this.stopListening();
|
|
159
|
+
|
|
160
|
+
if (this.connection) {
|
|
161
|
+
await this.connection.close();
|
|
162
|
+
this.connection = null;
|
|
163
|
+
log.debug('WebInspector connection closed');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (this.receivePromise) {
|
|
167
|
+
await this.receivePromise;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Get the connection ID being used for this service
|
|
173
|
+
* @returns The connection identifier
|
|
174
|
+
*/
|
|
175
|
+
getConnectionId(): string {
|
|
176
|
+
return this.connectionId;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Request application launch
|
|
181
|
+
* @param bundleId The bundle identifier of the application to launch
|
|
182
|
+
*/
|
|
183
|
+
async requestApplicationLaunch(bundleId: string): Promise<void> {
|
|
184
|
+
await this.sendMessage(WebInspectorService.RPC_REQUEST_APPLICATION_LAUNCH, {
|
|
185
|
+
WIRApplicationBundleIdentifierKey: bundleId,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Get connected applications
|
|
191
|
+
*/
|
|
192
|
+
async getConnectedApplications(): Promise<void> {
|
|
193
|
+
await this.sendMessage(
|
|
194
|
+
WebInspectorService.RPC_GET_CONNECTED_APPLICATIONS,
|
|
195
|
+
{},
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Forward get listing for an application
|
|
201
|
+
* @param appId The application identifier
|
|
202
|
+
*/
|
|
203
|
+
async forwardGetListing(appId: string): Promise<void> {
|
|
204
|
+
await this.sendMessage(WebInspectorService.RPC_FORWARD_GET_LISTING, {
|
|
205
|
+
WIRApplicationIdentifierKey: appId,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Forward automation session request
|
|
211
|
+
* @param sessionId The session identifier
|
|
212
|
+
* @param appId The application identifier
|
|
213
|
+
* @param capabilities Optional session capabilities
|
|
214
|
+
*/
|
|
215
|
+
async forwardAutomationSessionRequest(
|
|
216
|
+
sessionId: string,
|
|
217
|
+
appId: string,
|
|
218
|
+
capabilities?: PlistDictionary,
|
|
219
|
+
): Promise<void> {
|
|
220
|
+
const defaultCapabilities: PlistDictionary = {
|
|
221
|
+
'org.webkit.webdriver.webrtc.allow-insecure-media-capture': true,
|
|
222
|
+
'org.webkit.webdriver.webrtc.suppress-ice-candidate-filtering': false,
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
await this.sendMessage(
|
|
226
|
+
WebInspectorService.RPC_FORWARD_AUTOMATION_SESSION_REQUEST,
|
|
227
|
+
{
|
|
228
|
+
WIRApplicationIdentifierKey: appId,
|
|
229
|
+
WIRSessionIdentifierKey: sessionId,
|
|
230
|
+
WIRSessionCapabilitiesKey: {
|
|
231
|
+
...defaultCapabilities,
|
|
232
|
+
...(capabilities ?? {}),
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Forward socket setup for inspector connection
|
|
240
|
+
* @param sessionId The session identifier
|
|
241
|
+
* @param appId The application identifier
|
|
242
|
+
* @param pageId The page identifier
|
|
243
|
+
* @param automaticallyPause Whether to automatically pause (defaults to true)
|
|
244
|
+
*/
|
|
245
|
+
async forwardSocketSetup(
|
|
246
|
+
sessionId: string,
|
|
247
|
+
appId: string,
|
|
248
|
+
pageId: number,
|
|
249
|
+
automaticallyPause: boolean = true,
|
|
250
|
+
): Promise<void> {
|
|
251
|
+
const message: PlistDictionary = {
|
|
252
|
+
WIRApplicationIdentifierKey: appId,
|
|
253
|
+
WIRPageIdentifierKey: pageId,
|
|
254
|
+
WIRSenderKey: sessionId,
|
|
255
|
+
WIRMessageDataTypeChunkSupportedKey: 0,
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
if (!automaticallyPause) {
|
|
259
|
+
message.WIRAutomaticallyPause = false;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
await this.sendMessage(
|
|
263
|
+
WebInspectorService.RPC_FORWARD_SOCKET_SETUP,
|
|
264
|
+
message,
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Forward socket data to a page
|
|
270
|
+
* @param sessionId The session identifier
|
|
271
|
+
* @param appId The application identifier
|
|
272
|
+
* @param pageId The page identifier
|
|
273
|
+
* @param data The data to send (will be JSON stringified)
|
|
274
|
+
*/
|
|
275
|
+
async forwardSocketData(
|
|
276
|
+
sessionId: string,
|
|
277
|
+
appId: string,
|
|
278
|
+
pageId: number,
|
|
279
|
+
data: any,
|
|
280
|
+
): Promise<void> {
|
|
281
|
+
const socketData = typeof data === 'string' ? data : JSON.stringify(data);
|
|
282
|
+
|
|
283
|
+
await this.sendMessage(WebInspectorService.RPC_FORWARD_SOCKET_DATA, {
|
|
284
|
+
WIRApplicationIdentifierKey: appId,
|
|
285
|
+
WIRPageIdentifierKey: pageId,
|
|
286
|
+
WIRSessionIdentifierKey: sessionId,
|
|
287
|
+
WIRSenderKey: sessionId,
|
|
288
|
+
WIRSocketDataKey: Buffer.from(socketData, 'utf-8'),
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Forward indicate web view
|
|
294
|
+
* @param appId The application identifier
|
|
295
|
+
* @param pageId The page identifier
|
|
296
|
+
* @param enable Whether to enable indication
|
|
297
|
+
*/
|
|
298
|
+
async forwardIndicateWebView(
|
|
299
|
+
appId: string,
|
|
300
|
+
pageId: number,
|
|
301
|
+
enable: boolean,
|
|
302
|
+
): Promise<void> {
|
|
303
|
+
await this.sendMessage(WebInspectorService.RPC_FORWARD_INDICATE_WEB_VIEW, {
|
|
304
|
+
WIRApplicationIdentifierKey: appId,
|
|
305
|
+
WIRPageIdentifierKey: pageId,
|
|
306
|
+
WIRIndicateEnabledKey: enable,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Connect to the WebInspector service
|
|
312
|
+
* @returns Promise resolving to the ServiceConnection instance
|
|
313
|
+
*/
|
|
314
|
+
private async connectToWebInspectorService(): Promise<ServiceConnection> {
|
|
315
|
+
if (this.connection) {
|
|
316
|
+
return this.connection;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const service = {
|
|
320
|
+
serviceName: WebInspectorService.RSD_SERVICE_NAME,
|
|
321
|
+
port: this.address[1].toString(),
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
this.connection = await this.startLockdownService(service);
|
|
325
|
+
|
|
326
|
+
// Consume the StartService response from RSDCheckin
|
|
327
|
+
const startServiceResponse = await this.connection.receive();
|
|
328
|
+
if (startServiceResponse?.Request !== 'StartService') {
|
|
329
|
+
log.warn(
|
|
330
|
+
`Expected StartService response, got: ${JSON.stringify(startServiceResponse)}`,
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Send initial identifier report
|
|
335
|
+
await this.sendMessage(WebInspectorService.RPC_REPORT_IDENTIFIER, {});
|
|
336
|
+
|
|
337
|
+
log.debug('Connected to WebInspector service');
|
|
338
|
+
return this.connection;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Start receiving messages from the WebInspector service in the background
|
|
343
|
+
*/
|
|
344
|
+
private startMessageReceiver(): void {
|
|
345
|
+
if (this.isReceiving || !this.connection) {
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
this.isReceiving = true;
|
|
350
|
+
|
|
351
|
+
this.receivePromise = (async () => {
|
|
352
|
+
try {
|
|
353
|
+
while (this.isReceiving && this.connection) {
|
|
354
|
+
try {
|
|
355
|
+
const message = await this.connection.receive();
|
|
356
|
+
this.messageEmitter.emit('message', message);
|
|
357
|
+
} catch (error) {
|
|
358
|
+
if (this.isReceiving) {
|
|
359
|
+
log.error('Error receiving message:', error);
|
|
360
|
+
this.messageEmitter.emit('error', error);
|
|
361
|
+
}
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
} finally {
|
|
366
|
+
this.isReceiving = false;
|
|
367
|
+
}
|
|
368
|
+
})();
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
export default WebInspectorService;
|
package/src/services.ts
CHANGED
|
@@ -8,15 +8,19 @@ import type {
|
|
|
8
8
|
MobileConfigServiceWithConnection,
|
|
9
9
|
MobileImageMounterServiceWithConnection,
|
|
10
10
|
NotificationProxyServiceWithConnection,
|
|
11
|
+
PowerAssertionServiceWithConnection,
|
|
11
12
|
SpringboardServiceWithConnection,
|
|
12
13
|
SyslogService as SyslogServiceType,
|
|
14
|
+
WebInspectorServiceWithConnection,
|
|
13
15
|
} from './lib/types.js';
|
|
14
16
|
import DiagnosticsService from './services/ios/diagnostic-service/index.js';
|
|
15
17
|
import { MobileConfigService } from './services/ios/mobile-config/index.js';
|
|
16
18
|
import MobileImageMounterService from './services/ios/mobile-image-mounter/index.js';
|
|
17
19
|
import { NotificationProxyService } from './services/ios/notification-proxy/index.js';
|
|
20
|
+
import { PowerAssertionService } from './services/ios/power-assertion/index.js';
|
|
18
21
|
import { SpringBoardService } from './services/ios/springboard-service/index.js';
|
|
19
22
|
import SyslogService from './services/ios/syslog-service/index.js';
|
|
23
|
+
import { WebInspectorService } from './services/ios/webinspector/index.js';
|
|
20
24
|
|
|
21
25
|
const APPIUM_XCUITEST_DRIVER_NAME = 'appium-xcuitest-driver';
|
|
22
26
|
const TUNNEL_REGISTRY_PORT = 'tunnelRegistryPort';
|
|
@@ -100,6 +104,22 @@ export async function startSpringboardService(
|
|
|
100
104
|
};
|
|
101
105
|
}
|
|
102
106
|
|
|
107
|
+
export async function startPowerAssertionService(
|
|
108
|
+
udid: string,
|
|
109
|
+
): Promise<PowerAssertionServiceWithConnection> {
|
|
110
|
+
const { remoteXPC, tunnelConnection } = await createRemoteXPCConnection(udid);
|
|
111
|
+
const powerAssertionService = remoteXPC.findService(
|
|
112
|
+
PowerAssertionService.RSD_SERVICE_NAME,
|
|
113
|
+
);
|
|
114
|
+
return {
|
|
115
|
+
remoteXPC: remoteXPC as RemoteXpcConnection,
|
|
116
|
+
powerAssertionService: new PowerAssertionService([
|
|
117
|
+
tunnelConnection.host,
|
|
118
|
+
parseInt(powerAssertionService.port, 10),
|
|
119
|
+
]),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
103
123
|
export async function startSyslogService(
|
|
104
124
|
udid: string,
|
|
105
125
|
): Promise<SyslogServiceType> {
|
|
@@ -107,6 +127,22 @@ export async function startSyslogService(
|
|
|
107
127
|
return new SyslogService([tunnelConnection.host, tunnelConnection.port]);
|
|
108
128
|
}
|
|
109
129
|
|
|
130
|
+
export async function startWebInspectorService(
|
|
131
|
+
udid: string,
|
|
132
|
+
): Promise<WebInspectorServiceWithConnection> {
|
|
133
|
+
const { remoteXPC, tunnelConnection } = await createRemoteXPCConnection(udid);
|
|
134
|
+
const webInspectorService = remoteXPC.findService(
|
|
135
|
+
WebInspectorService.RSD_SERVICE_NAME,
|
|
136
|
+
);
|
|
137
|
+
return {
|
|
138
|
+
remoteXPC: remoteXPC as RemoteXpcConnection,
|
|
139
|
+
webInspectorService: new WebInspectorService([
|
|
140
|
+
tunnelConnection.host,
|
|
141
|
+
parseInt(webInspectorService.port, 10),
|
|
142
|
+
]),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
110
146
|
export async function createRemoteXPCConnection(udid: string) {
|
|
111
147
|
const tunnelConnection = await getTunnelInformation(udid);
|
|
112
148
|
const remoteXPC = await startService(
|