appium-ios-remotexpc 0.4.2 → 0.5.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 CHANGED
@@ -1,3 +1,9 @@
1
+ ## [0.5.0](https://github.com/appium/appium-ios-remotexpc/compare/v0.4.2...v0.5.0) (2025-09-29)
2
+
3
+ ### Features
4
+
5
+ * implement `mcinstall` service ([#71](https://github.com/appium/appium-ios-remotexpc/issues/71)) ([dbd2a6d](https://github.com/appium/appium-ios-remotexpc/commit/dbd2a6dece3d4994d301b0891fff20af77c1a1f2))
6
+
1
7
  ## [0.4.2](https://github.com/appium/appium-ios-remotexpc/compare/v0.4.1...v0.4.2) (2025-09-16)
2
8
 
3
9
  ### Miscellaneous Chores
@@ -33,4 +33,5 @@ export declare const BPLIST_TYPE: {
33
33
  SET: number;
34
34
  DICT: number;
35
35
  };
36
+ export declare const SUPPORTED_EXTENSIONS: readonly [".pem", ".cer", ".crt", ".p12", ".pfx", ".mobileconfig", ".plist"];
36
37
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/lib/plist/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,eAAO,MAAM,YAAY,WAAW,CAAC;AACrC,eAAO,MAAM,cAAc,OAAO,CAAC;AACnC,eAAO,MAAM,wBAAwB,qBAEpC,CAAC;AAGF,eAAO,MAAM,kBAAkB,aAAa,CAAC;AAC7C,eAAO,MAAM,mBAAmB,cAAc,CAAC;AAC/C,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAG5C,eAAO,MAAM,eAAe,UAAU,CAAC;AACvC,eAAO,MAAM,iBAAiB,aAAa,CAAC;AAG5C,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,eAAO,MAAM,sBAAsB,aAAc,CAAC;AAGlD,eAAO,MAAM,aAAa,SAAS,CAAC;AAGpC,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAG5C,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAGtC,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;CAevB,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/lib/plist/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,eAAO,MAAM,YAAY,WAAW,CAAC;AACrC,eAAO,MAAM,cAAc,OAAO,CAAC;AACnC,eAAO,MAAM,wBAAwB,qBAEpC,CAAC;AAGF,eAAO,MAAM,kBAAkB,aAAa,CAAC;AAC7C,eAAO,MAAM,mBAAmB,cAAc,CAAC;AAC/C,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAG5C,eAAO,MAAM,eAAe,UAAU,CAAC;AACvC,eAAO,MAAM,iBAAiB,aAAa,CAAC;AAG5C,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,eAAO,MAAM,sBAAsB,aAAc,CAAC;AAGlD,eAAO,MAAM,aAAa,SAAS,CAAC;AAGpC,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAG5C,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAGtC,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;CAevB,CAAC;AAGF,eAAO,MAAM,oBAAoB,8EAQvB,CAAC"}
@@ -41,3 +41,13 @@ export const BPLIST_TYPE = {
41
41
  SET: 0xc0,
42
42
  DICT: 0xd0,
43
43
  };
44
+ // Supported file extensions for plist-related file
45
+ export const SUPPORTED_EXTENSIONS = [
46
+ '.pem',
47
+ '.cer',
48
+ '.crt',
49
+ '.p12',
50
+ '.pfx',
51
+ '.mobileconfig',
52
+ '.plist',
53
+ ];
@@ -174,6 +174,56 @@ export interface NotificationProxyService extends BaseService {
174
174
  */
175
175
  expectNotification(timeout?: number): Promise<PlistMessage>;
176
176
  }
177
+ /**
178
+ * Represents the static side of MobileConfigService
179
+ */
180
+ export interface MobileConfigService extends BaseService {
181
+ /**
182
+ * Connect to the mobile config service
183
+ * @returns Promise resolving to the ServiceConnection instance
184
+ */
185
+ connectToMobileConfigService(): Promise<ServiceConnection>;
186
+ /**
187
+ * Get all profiles of iOS devices
188
+ * @returns {Promise<PlistDictionary>}
189
+ * e.g.
190
+ * {
191
+ * OrderedIdentifiers: [ '2fac1c2b3d684843189b2981c718b0132854a847a' ],
192
+ * ProfileManifest: {
193
+ * '2fac1c2b3d684843189b2981c718b0132854a847a': {
194
+ * Description: 'Charles Proxy CA (7 Dec 2020, MacBook-Pro.local)',
195
+ * IsActive: true
196
+ * }
197
+ * },
198
+ * ProfileMetadata: {
199
+ * '2fac1c2b3d684843189b2981c718b0132854a847a': {
200
+ * PayloadDisplayName: 'Charles Proxy CA (7 Dec 2020, MacBook-Pro.local)',
201
+ * PayloadRemovalDisallowed: false,
202
+ * PayloadUUID: 'B30005CC-BC73-4E42-8545-8DA6C44A8A71',
203
+ * PayloadVersion: 1
204
+ * }
205
+ * },
206
+ * Status: 'Acknowledged'
207
+ * }
208
+ */
209
+ getProfileList(): Promise<PlistDictionary>;
210
+ /**
211
+ * Install profile to iOS device
212
+ * @param {String} path must be a certificate file .PEM .CER and more formats
213
+ * e.g: /Downloads/charles-certificate.pem
214
+ */
215
+ installProfileFromPath(path: string): Promise<void>;
216
+ /**
217
+ * Install profile to iOS device from buffer
218
+ * @param {Buffer} payload must be a certificate file .PEM .CER and more formats
219
+ */
220
+ installProfileFromBuffer(payload: Buffer): Promise<void>;
221
+ /**
222
+ * Remove profile from iOS device
223
+ * @param {String} identifier Query identifier list through getProfileList method
224
+ */
225
+ removeProfile(identifier: string): Promise<void>;
226
+ }
177
227
  /**
178
228
  * Represents the static side of DiagnosticsService
179
229
  */
@@ -208,6 +258,16 @@ export interface NotificationProxyServiceWithConnection {
208
258
  /** The RemoteXPC connection that can be used to close the connection */
209
259
  remoteXPC: RemoteXpcConnection;
210
260
  }
261
+ /**
262
+ * Represents a MobileConfigService instance with its associated RemoteXPC connection
263
+ * This allows callers to properly manage the connection lifecycle
264
+ */
265
+ export interface MobileConfigServiceWithConnection {
266
+ /** The MobileConfigService instance */
267
+ mobileConfigService: MobileConfigService;
268
+ /** The RemoteXPC connection that can be used to close the connection */
269
+ remoteXPC: RemoteXpcConnection;
270
+ }
211
271
  /**
212
272
  * Options for configuring syslog capture
213
273
  */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import { type MobileConfigService as MobileConfigServiceInterface, type PlistDictionary } from '../../../lib/types.js';
2
+ import { ServiceConnection } from '../../../service-connection.js';
3
+ import { BaseService } from '../base-service.js';
4
+ /**
5
+ * MobileConfigService provides an API to:
6
+ * - Install configuration profiles
7
+ * - Remove configuration profiles
8
+ * - List installed configuration profiles
9
+ */
10
+ declare class MobileConfigService extends BaseService implements MobileConfigServiceInterface {
11
+ static readonly RSD_SERVICE_NAME = "com.apple.mobile.MCInstall.shim.remote";
12
+ private _conn;
13
+ constructor(address: [string, number]);
14
+ /**
15
+ * Connect to the mobile config service
16
+ * @returns Promise resolving to the ServiceConnection instance
17
+ */
18
+ connectToMobileConfigService(): Promise<ServiceConnection>;
19
+ /**
20
+ * Get all profiles of iOS devices
21
+ * @returns {Promise<PlistDictionary>}
22
+ * e.g.
23
+ * {
24
+ * OrderedIdentifiers: [ '2fac1c2b3d684843189b2981c718b0132854a847a' ],
25
+ * ProfileManifest: {
26
+ * '2fac1c2b3d684843189b2981c718b0132854a847a': {
27
+ * Description: 'Charles Proxy CA (7 Dec 2020, MacBook-Pro.local)',
28
+ * IsActive: true
29
+ * }
30
+ * },
31
+ * ProfileMetadata: {
32
+ * '2fac1c2b3d684843189b2981c718b0132854a847a': {
33
+ * PayloadDisplayName: 'Charles Proxy CA (7 Dec 2020, MacBook-Pro.local)',
34
+ * PayloadRemovalDisallowed: false,
35
+ * PayloadUUID: 'B30005CC-BC73-4E42-8545-8DA6C44A8A71',
36
+ * PayloadVersion: 1
37
+ * }
38
+ * },
39
+ * Status: 'Acknowledged'
40
+ * }
41
+ */
42
+ getProfileList(): Promise<PlistDictionary>;
43
+ /**
44
+ * Install profile from path to iOS device
45
+ * The phone must be unlocked before installing the profile
46
+ * @param {String} filePath must be a certificate file .PEM .CER and more formats
47
+ * e.g: /Downloads/charles-certificate.pem
48
+ */
49
+ installProfileFromPath(filePath: string): Promise<void>;
50
+ /**
51
+ * Install profile to iOS device from buffer
52
+ * The phone must be unlocked before installing the profile
53
+ * @param {Buffer} payload must be a certificate file buffer .PEM .CER and more formats
54
+ */
55
+ installProfileFromBuffer(payload: Buffer): Promise<void>;
56
+ /**
57
+ * Remove profile from iOS device
58
+ * @param {String} identifier Query identifier list through getProfileList method
59
+ */
60
+ removeProfile(identifier: string): Promise<void>;
61
+ private _sendPlistAndReceive;
62
+ private getServiceConfig;
63
+ }
64
+ export { MobileConfigService };
65
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/services/ios/mobile-config/index.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,KAAK,mBAAmB,IAAI,4BAA4B,EACxD,KAAK,eAAe,EACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAKjD;;;;;GAKG;AACH,cAAM,mBACJ,SAAQ,WACR,YAAW,4BAA4B;IAEvC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,4CAA4C;IAC5E,OAAO,CAAC,KAAK,CAAkC;gBAEnC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;IAGrC;;;OAGG;IACG,4BAA4B,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAUhE;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACG,cAAc,IAAI,OAAO,CAAC,eAAe,CAAC;IAQhD;;;;;OAKG;IACG,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsB7D;;;;OAIG;IACG,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAc9D;;;OAGG;IACG,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YA0CxC,oBAAoB;IAuBlC,OAAO,CAAC,gBAAgB;CASzB;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,166 @@
1
+ import { fs, logger } from '@appium/support';
2
+ import path from 'node:path';
3
+ import { SUPPORTED_EXTENSIONS } from '../../../lib/plist/constants.js';
4
+ import { createPlist, parsePlist } from '../../../lib/plist/index.js';
5
+ import {} from '../../../lib/types.js';
6
+ import { ServiceConnection } from '../../../service-connection.js';
7
+ import { BaseService } from '../base-service.js';
8
+ const ERROR_CLOUD_CONFIGURATION_ALREADY_PRESENT = 14002;
9
+ const log = logger.getLogger('MobileConfigService');
10
+ /**
11
+ * MobileConfigService provides an API to:
12
+ * - Install configuration profiles
13
+ * - Remove configuration profiles
14
+ * - List installed configuration profiles
15
+ */
16
+ class MobileConfigService extends BaseService {
17
+ static RSD_SERVICE_NAME = 'com.apple.mobile.MCInstall.shim.remote';
18
+ _conn = null;
19
+ constructor(address) {
20
+ super(address);
21
+ }
22
+ /**
23
+ * Connect to the mobile config service
24
+ * @returns Promise resolving to the ServiceConnection instance
25
+ */
26
+ async connectToMobileConfigService() {
27
+ if (this._conn) {
28
+ return this._conn;
29
+ }
30
+ const service = this.getServiceConfig();
31
+ this._conn = await this.startLockdownService(service);
32
+ return this._conn;
33
+ }
34
+ /**
35
+ * Get all profiles of iOS devices
36
+ * @returns {Promise<PlistDictionary>}
37
+ * e.g.
38
+ * {
39
+ * OrderedIdentifiers: [ '2fac1c2b3d684843189b2981c718b0132854a847a' ],
40
+ * ProfileManifest: {
41
+ * '2fac1c2b3d684843189b2981c718b0132854a847a': {
42
+ * Description: 'Charles Proxy CA (7 Dec 2020, MacBook-Pro.local)',
43
+ * IsActive: true
44
+ * }
45
+ * },
46
+ * ProfileMetadata: {
47
+ * '2fac1c2b3d684843189b2981c718b0132854a847a': {
48
+ * PayloadDisplayName: 'Charles Proxy CA (7 Dec 2020, MacBook-Pro.local)',
49
+ * PayloadRemovalDisallowed: false,
50
+ * PayloadUUID: 'B30005CC-BC73-4E42-8545-8DA6C44A8A71',
51
+ * PayloadVersion: 1
52
+ * }
53
+ * },
54
+ * Status: 'Acknowledged'
55
+ * }
56
+ */
57
+ async getProfileList() {
58
+ const req = {
59
+ RequestType: 'GetProfileList',
60
+ };
61
+ return this._sendPlistAndReceive(req);
62
+ }
63
+ /**
64
+ * Install profile from path to iOS device
65
+ * The phone must be unlocked before installing the profile
66
+ * @param {String} filePath must be a certificate file .PEM .CER and more formats
67
+ * e.g: /Downloads/charles-certificate.pem
68
+ */
69
+ async installProfileFromPath(filePath) {
70
+ // Check if file exists
71
+ try {
72
+ await fs.access(filePath);
73
+ }
74
+ catch (error) {
75
+ throw new Error(`Profile filepath does not exist: ${filePath}`);
76
+ }
77
+ const fileExtension = path.extname(filePath).toLowerCase();
78
+ if (!fileExtension ||
79
+ !SUPPORTED_EXTENSIONS.includes(fileExtension)) {
80
+ throw new Error(`Unsupported file format. Supported formats: ${SUPPORTED_EXTENSIONS.join(', ')}`);
81
+ }
82
+ const payload = await fs.readFile(filePath);
83
+ await this.installProfileFromBuffer(payload);
84
+ }
85
+ /**
86
+ * Install profile to iOS device from buffer
87
+ * The phone must be unlocked before installing the profile
88
+ * @param {Buffer} payload must be a certificate file buffer .PEM .CER and more formats
89
+ */
90
+ async installProfileFromBuffer(payload) {
91
+ try {
92
+ const req = {
93
+ RequestType: 'InstallProfile',
94
+ Payload: parsePlist(payload),
95
+ };
96
+ await this._sendPlistAndReceive(req);
97
+ }
98
+ catch (error) {
99
+ if (error instanceof Error) {
100
+ throw new Error(`Failed to install profile: ${error.message}`);
101
+ }
102
+ throw error;
103
+ }
104
+ }
105
+ /**
106
+ * Remove profile from iOS device
107
+ * @param {String} identifier Query identifier list through getProfileList method
108
+ */
109
+ async removeProfile(identifier) {
110
+ const profileList = await this.getProfileList();
111
+ if (!profileList?.ProfileMetadata) {
112
+ return;
113
+ }
114
+ const profileMetadata = profileList.ProfileMetadata;
115
+ if (!(identifier in profileMetadata)) {
116
+ // Get available identifiers from OrderedIdentifiers array or ProfileMetadata keys
117
+ let availableIdentifiers;
118
+ if (profileList.OrderedIdentifiers &&
119
+ Array.isArray(profileList.OrderedIdentifiers)) {
120
+ availableIdentifiers = profileList.OrderedIdentifiers;
121
+ }
122
+ else {
123
+ availableIdentifiers = Object.keys(profileMetadata);
124
+ }
125
+ throw new Error(`Trying to remove not installed profile: ${identifier}. Expected one of: ${availableIdentifiers.join(', ')}`);
126
+ }
127
+ const meta = profileMetadata[identifier];
128
+ const payloadData = {
129
+ PayloadIdentifier: identifier,
130
+ PayloadType: 'Configuration',
131
+ PayloadUUID: meta.PayloadUUID,
132
+ PayloadVersion: meta.PayloadVersion,
133
+ };
134
+ const req = {
135
+ RequestType: 'RemoveProfile',
136
+ ProfileIdentifier: createPlist(payloadData),
137
+ };
138
+ log.info(req);
139
+ await this._sendPlistAndReceive(req);
140
+ }
141
+ async _sendPlistAndReceive(req) {
142
+ if (!this._conn) {
143
+ this._conn = await this.connectToMobileConfigService();
144
+ }
145
+ // Ignore first response as it is just status check
146
+ await this._conn.sendAndReceive(req);
147
+ const res = await this._conn.sendAndReceive(req);
148
+ if (res.Status !== 'Acknowledged') {
149
+ const errorCode = res.ErrorChain?.[0]?.ErrorCode;
150
+ if (Number.isInteger(errorCode)) {
151
+ if (errorCode === ERROR_CLOUD_CONFIGURATION_ALREADY_PRESENT) {
152
+ throw new Error('A cloud configuration is already present on device. You must first erase the device to install a new configuration.');
153
+ }
154
+ }
155
+ throw new Error(`Invalid response: ${JSON.stringify(res)}`);
156
+ }
157
+ return res;
158
+ }
159
+ getServiceConfig() {
160
+ return {
161
+ serviceName: MobileConfigService.RSD_SERVICE_NAME,
162
+ port: this.address[1].toString(),
163
+ };
164
+ }
165
+ }
166
+ export { MobileConfigService };
@@ -1,7 +1,8 @@
1
1
  import { RemoteXpcConnection } from './lib/remote-xpc/remote-xpc-connection.js';
2
- import type { DiagnosticsServiceWithConnection, MobileImageMounterServiceWithConnection, NotificationProxyServiceWithConnection, SyslogService as SyslogServiceType } from './lib/types.js';
2
+ import type { DiagnosticsServiceWithConnection, MobileConfigServiceWithConnection, MobileImageMounterServiceWithConnection, NotificationProxyServiceWithConnection, SyslogService as SyslogServiceType } from './lib/types.js';
3
3
  export declare function startDiagnosticsService(udid: string): Promise<DiagnosticsServiceWithConnection>;
4
4
  export declare function startNotificationProxyService(udid: string): Promise<NotificationProxyServiceWithConnection>;
5
+ export declare function startMobileConfigService(udid: string): Promise<MobileConfigServiceWithConnection>;
5
6
  export declare function startMobileImageMounterService(udid: string): Promise<MobileImageMounterServiceWithConnection>;
6
7
  export declare function startSyslogService(udid: string): Promise<SyslogServiceType>;
7
8
  export declare function createRemoteXPCConnection(udid: string): Promise<{
@@ -1 +1 @@
1
- {"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../../src/services.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC;AAGhF,OAAO,KAAK,EACV,gCAAgC,EAChC,uCAAuC,EACvC,sCAAsC,EACtC,aAAa,IAAI,iBAAiB,EACnC,MAAM,gBAAgB,CAAC;AASxB,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,gCAAgC,CAAC,CAY3C;AAED,wBAAsB,6BAA6B,CACjD,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,sCAAsC,CAAC,CAYjD;AAED,wBAAsB,8BAA8B,CAClD,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,uCAAuC,CAAC,CAYlD;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,iBAAiB,CAAC,CAG5B;AAED,wBAAsB,yBAAyB,CAAC,IAAI,EAAE,MAAM;;;;;;;;GAO3D"}
1
+ {"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../../src/services.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC;AAGhF,OAAO,KAAK,EACV,gCAAgC,EAChC,iCAAiC,EACjC,uCAAuC,EACvC,sCAAsC,EACtC,aAAa,IAAI,iBAAiB,EACnC,MAAM,gBAAgB,CAAC;AAUxB,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,gCAAgC,CAAC,CAY3C;AAED,wBAAsB,6BAA6B,CACjD,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,sCAAsC,CAAC,CAYjD;AAED,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,iCAAiC,CAAC,CAY5C;AACD,wBAAsB,8BAA8B,CAClD,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,uCAAuC,CAAC,CAYlD;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,iBAAiB,CAAC,CAG5B;AAED,wBAAsB,yBAAyB,CAAC,IAAI,EAAE,MAAM;;;;;;;;GAO3D"}
@@ -3,6 +3,7 @@ import { RemoteXpcConnection } from './lib/remote-xpc/remote-xpc-connection.js';
3
3
  import { TunnelManager } from './lib/tunnel/index.js';
4
4
  import { TunnelApiClient } from './lib/tunnel/tunnel-api-client.js';
5
5
  import DiagnosticsService from './services/ios/diagnostic-service/index.js';
6
+ import { MobileConfigService } from './services/ios/mobile-config/index.js';
6
7
  import MobileImageMounterService from './services/ios/mobile-image-mounter/index.js';
7
8
  import { NotificationProxyService } from './services/ios/notification-proxy/index.js';
8
9
  import SyslogService from './services/ios/syslog-service/index.js';
@@ -30,6 +31,17 @@ export async function startNotificationProxyService(udid) {
30
31
  ]),
31
32
  };
32
33
  }
34
+ export async function startMobileConfigService(udid) {
35
+ const { remoteXPC, tunnelConnection } = await createRemoteXPCConnection(udid);
36
+ const mobileConfigService = remoteXPC.findService(MobileConfigService.RSD_SERVICE_NAME);
37
+ return {
38
+ remoteXPC: remoteXPC,
39
+ mobileConfigService: new MobileConfigService([
40
+ tunnelConnection.host,
41
+ parseInt(mobileConfigService.port, 10),
42
+ ]),
43
+ };
44
+ }
33
45
  export async function startMobileImageMounterService(udid) {
34
46
  const { remoteXPC, tunnelConnection } = await createRemoteXPCConnection(udid);
35
47
  const mobileImageMounterService = remoteXPC.findService(MobileImageMounterService.RSD_SERVICE_NAME);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appium-ios-remotexpc",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "main": "build/src/index.js",
5
5
  "types": "build/src/index.d.ts",
6
6
  "type": "module",
@@ -51,3 +51,14 @@ export const BPLIST_TYPE = {
51
51
  SET: 0xc0,
52
52
  DICT: 0xd0,
53
53
  };
54
+
55
+ // Supported file extensions for plist-related file
56
+ export const SUPPORTED_EXTENSIONS = [
57
+ '.pem',
58
+ '.cer',
59
+ '.crt',
60
+ '.p12',
61
+ '.pfx',
62
+ '.mobileconfig',
63
+ '.plist',
64
+ ] as const;
package/src/lib/types.ts CHANGED
@@ -212,6 +212,57 @@ export interface NotificationProxyService extends BaseService {
212
212
  expectNotification(timeout?: number): Promise<PlistMessage>;
213
213
  }
214
214
 
215
+ /**
216
+ * Represents the static side of MobileConfigService
217
+ */
218
+ export interface MobileConfigService extends BaseService {
219
+ /**
220
+ * Connect to the mobile config service
221
+ * @returns Promise resolving to the ServiceConnection instance
222
+ */
223
+ connectToMobileConfigService(): Promise<ServiceConnection>;
224
+ /**
225
+ * Get all profiles of iOS devices
226
+ * @returns {Promise<PlistDictionary>}
227
+ * e.g.
228
+ * {
229
+ * OrderedIdentifiers: [ '2fac1c2b3d684843189b2981c718b0132854a847a' ],
230
+ * ProfileManifest: {
231
+ * '2fac1c2b3d684843189b2981c718b0132854a847a': {
232
+ * Description: 'Charles Proxy CA (7 Dec 2020, MacBook-Pro.local)',
233
+ * IsActive: true
234
+ * }
235
+ * },
236
+ * ProfileMetadata: {
237
+ * '2fac1c2b3d684843189b2981c718b0132854a847a': {
238
+ * PayloadDisplayName: 'Charles Proxy CA (7 Dec 2020, MacBook-Pro.local)',
239
+ * PayloadRemovalDisallowed: false,
240
+ * PayloadUUID: 'B30005CC-BC73-4E42-8545-8DA6C44A8A71',
241
+ * PayloadVersion: 1
242
+ * }
243
+ * },
244
+ * Status: 'Acknowledged'
245
+ * }
246
+ */
247
+ getProfileList(): Promise<PlistDictionary>;
248
+ /**
249
+ * Install profile to iOS device
250
+ * @param {String} path must be a certificate file .PEM .CER and more formats
251
+ * e.g: /Downloads/charles-certificate.pem
252
+ */
253
+ installProfileFromPath(path: string): Promise<void>;
254
+ /**
255
+ * Install profile to iOS device from buffer
256
+ * @param {Buffer} payload must be a certificate file .PEM .CER and more formats
257
+ */
258
+ installProfileFromBuffer(payload: Buffer): Promise<void>;
259
+ /**
260
+ * Remove profile from iOS device
261
+ * @param {String} identifier Query identifier list through getProfileList method
262
+ */
263
+ removeProfile(identifier: string): Promise<void>;
264
+ }
265
+
215
266
  /**
216
267
  * Represents the static side of DiagnosticsService
217
268
  */
@@ -249,6 +300,17 @@ export interface NotificationProxyServiceWithConnection {
249
300
  remoteXPC: RemoteXpcConnection;
250
301
  }
251
302
 
303
+ /**
304
+ * Represents a MobileConfigService instance with its associated RemoteXPC connection
305
+ * This allows callers to properly manage the connection lifecycle
306
+ */
307
+ export interface MobileConfigServiceWithConnection {
308
+ /** The MobileConfigService instance */
309
+ mobileConfigService: MobileConfigService;
310
+ /** The RemoteXPC connection that can be used to close the connection */
311
+ remoteXPC: RemoteXpcConnection;
312
+ }
313
+
252
314
  /**
253
315
  * Options for configuring syslog capture
254
316
  */
@@ -0,0 +1,204 @@
1
+ import { fs, logger } from '@appium/support';
2
+ import path from 'node:path';
3
+
4
+ import { SUPPORTED_EXTENSIONS } from '../../../lib/plist/constants.js';
5
+ import { createPlist, parsePlist } from '../../../lib/plist/index.js';
6
+ import {
7
+ type MobileConfigService as MobileConfigServiceInterface,
8
+ type PlistDictionary,
9
+ } from '../../../lib/types.js';
10
+ import { ServiceConnection } from '../../../service-connection.js';
11
+ import { BaseService } from '../base-service.js';
12
+
13
+ const ERROR_CLOUD_CONFIGURATION_ALREADY_PRESENT = 14002;
14
+ const log = logger.getLogger('MobileConfigService');
15
+
16
+ /**
17
+ * MobileConfigService provides an API to:
18
+ * - Install configuration profiles
19
+ * - Remove configuration profiles
20
+ * - List installed configuration profiles
21
+ */
22
+ class MobileConfigService
23
+ extends BaseService
24
+ implements MobileConfigServiceInterface
25
+ {
26
+ static readonly RSD_SERVICE_NAME = 'com.apple.mobile.MCInstall.shim.remote';
27
+ private _conn: ServiceConnection | null = null;
28
+
29
+ constructor(address: [string, number]) {
30
+ super(address);
31
+ }
32
+ /**
33
+ * Connect to the mobile config service
34
+ * @returns Promise resolving to the ServiceConnection instance
35
+ */
36
+ async connectToMobileConfigService(): Promise<ServiceConnection> {
37
+ if (this._conn) {
38
+ return this._conn;
39
+ }
40
+
41
+ const service = this.getServiceConfig();
42
+ this._conn = await this.startLockdownService(service);
43
+ return this._conn;
44
+ }
45
+
46
+ /**
47
+ * Get all profiles of iOS devices
48
+ * @returns {Promise<PlistDictionary>}
49
+ * e.g.
50
+ * {
51
+ * OrderedIdentifiers: [ '2fac1c2b3d684843189b2981c718b0132854a847a' ],
52
+ * ProfileManifest: {
53
+ * '2fac1c2b3d684843189b2981c718b0132854a847a': {
54
+ * Description: 'Charles Proxy CA (7 Dec 2020, MacBook-Pro.local)',
55
+ * IsActive: true
56
+ * }
57
+ * },
58
+ * ProfileMetadata: {
59
+ * '2fac1c2b3d684843189b2981c718b0132854a847a': {
60
+ * PayloadDisplayName: 'Charles Proxy CA (7 Dec 2020, MacBook-Pro.local)',
61
+ * PayloadRemovalDisallowed: false,
62
+ * PayloadUUID: 'B30005CC-BC73-4E42-8545-8DA6C44A8A71',
63
+ * PayloadVersion: 1
64
+ * }
65
+ * },
66
+ * Status: 'Acknowledged'
67
+ * }
68
+ */
69
+ async getProfileList(): Promise<PlistDictionary> {
70
+ const req = {
71
+ RequestType: 'GetProfileList',
72
+ };
73
+
74
+ return this._sendPlistAndReceive(req);
75
+ }
76
+
77
+ /**
78
+ * Install profile from path to iOS device
79
+ * The phone must be unlocked before installing the profile
80
+ * @param {String} filePath must be a certificate file .PEM .CER and more formats
81
+ * e.g: /Downloads/charles-certificate.pem
82
+ */
83
+ async installProfileFromPath(filePath: string): Promise<void> {
84
+ // Check if file exists
85
+ try {
86
+ await fs.access(filePath);
87
+ } catch (error) {
88
+ throw new Error(`Profile filepath does not exist: ${filePath}`);
89
+ }
90
+
91
+ const fileExtension = path.extname(filePath).toLowerCase();
92
+ if (
93
+ !fileExtension ||
94
+ !SUPPORTED_EXTENSIONS.includes(fileExtension as any)
95
+ ) {
96
+ throw new Error(
97
+ `Unsupported file format. Supported formats: ${SUPPORTED_EXTENSIONS.join(', ')}`,
98
+ );
99
+ }
100
+
101
+ const payload = await fs.readFile(filePath);
102
+ await this.installProfileFromBuffer(payload);
103
+ }
104
+
105
+ /**
106
+ * Install profile to iOS device from buffer
107
+ * The phone must be unlocked before installing the profile
108
+ * @param {Buffer} payload must be a certificate file buffer .PEM .CER and more formats
109
+ */
110
+ async installProfileFromBuffer(payload: Buffer): Promise<void> {
111
+ try {
112
+ const req = {
113
+ RequestType: 'InstallProfile',
114
+ Payload: parsePlist(payload),
115
+ };
116
+ await this._sendPlistAndReceive(req);
117
+ } catch (error) {
118
+ if (error instanceof Error) {
119
+ throw new Error(`Failed to install profile: ${error.message}`);
120
+ }
121
+ throw error;
122
+ }
123
+ }
124
+ /**
125
+ * Remove profile from iOS device
126
+ * @param {String} identifier Query identifier list through getProfileList method
127
+ */
128
+ async removeProfile(identifier: string): Promise<void> {
129
+ const profileList = await this.getProfileList();
130
+ if (!profileList?.ProfileMetadata) {
131
+ return;
132
+ }
133
+
134
+ const profileMetadata = profileList.ProfileMetadata as Record<string, any>;
135
+ if (!(identifier in profileMetadata)) {
136
+ // Get available identifiers from OrderedIdentifiers array or ProfileMetadata keys
137
+ let availableIdentifiers: string[];
138
+ if (
139
+ profileList.OrderedIdentifiers &&
140
+ Array.isArray(profileList.OrderedIdentifiers)
141
+ ) {
142
+ availableIdentifiers = profileList.OrderedIdentifiers as string[];
143
+ } else {
144
+ availableIdentifiers = Object.keys(profileMetadata);
145
+ }
146
+
147
+ throw new Error(
148
+ `Trying to remove not installed profile: ${identifier}. Expected one of: ${availableIdentifiers.join(', ')}`,
149
+ );
150
+ }
151
+
152
+ const meta = profileMetadata[identifier];
153
+ const payloadData = {
154
+ PayloadIdentifier: identifier,
155
+ PayloadType: 'Configuration',
156
+ PayloadUUID: meta.PayloadUUID,
157
+ PayloadVersion: meta.PayloadVersion,
158
+ };
159
+
160
+ const req = {
161
+ RequestType: 'RemoveProfile',
162
+ ProfileIdentifier: createPlist(payloadData),
163
+ };
164
+
165
+ log.info(req);
166
+
167
+ await this._sendPlistAndReceive(req);
168
+ }
169
+
170
+ private async _sendPlistAndReceive(
171
+ req: PlistDictionary,
172
+ ): Promise<PlistDictionary> {
173
+ if (!this._conn) {
174
+ this._conn = await this.connectToMobileConfigService();
175
+ }
176
+ // Ignore first response as it is just status check
177
+ await this._conn.sendAndReceive(req);
178
+ const res = await this._conn.sendAndReceive(req);
179
+ if (res.Status !== 'Acknowledged') {
180
+ const errorCode = (res.ErrorChain as any[])?.[0]?.ErrorCode;
181
+ if (Number.isInteger(errorCode)) {
182
+ if (errorCode === ERROR_CLOUD_CONFIGURATION_ALREADY_PRESENT) {
183
+ throw new Error(
184
+ 'A cloud configuration is already present on device. You must first erase the device to install a new configuration.',
185
+ );
186
+ }
187
+ }
188
+ throw new Error(`Invalid response: ${JSON.stringify(res)}`);
189
+ }
190
+ return res;
191
+ }
192
+
193
+ private getServiceConfig(): {
194
+ serviceName: string;
195
+ port: string;
196
+ } {
197
+ return {
198
+ serviceName: MobileConfigService.RSD_SERVICE_NAME,
199
+ port: this.address[1].toString(),
200
+ };
201
+ }
202
+ }
203
+
204
+ export { MobileConfigService };
package/src/services.ts CHANGED
@@ -5,11 +5,13 @@ import { TunnelManager } from './lib/tunnel/index.js';
5
5
  import { TunnelApiClient } from './lib/tunnel/tunnel-api-client.js';
6
6
  import type {
7
7
  DiagnosticsServiceWithConnection,
8
+ MobileConfigServiceWithConnection,
8
9
  MobileImageMounterServiceWithConnection,
9
10
  NotificationProxyServiceWithConnection,
10
11
  SyslogService as SyslogServiceType,
11
12
  } from './lib/types.js';
12
13
  import DiagnosticsService from './services/ios/diagnostic-service/index.js';
14
+ import { MobileConfigService } from './services/ios/mobile-config/index.js';
13
15
  import MobileImageMounterService from './services/ios/mobile-image-mounter/index.js';
14
16
  import { NotificationProxyService } from './services/ios/notification-proxy/index.js';
15
17
  import SyslogService from './services/ios/syslog-service/index.js';
@@ -49,6 +51,21 @@ export async function startNotificationProxyService(
49
51
  };
50
52
  }
51
53
 
54
+ export async function startMobileConfigService(
55
+ udid: string,
56
+ ): Promise<MobileConfigServiceWithConnection> {
57
+ const { remoteXPC, tunnelConnection } = await createRemoteXPCConnection(udid);
58
+ const mobileConfigService = remoteXPC.findService(
59
+ MobileConfigService.RSD_SERVICE_NAME,
60
+ );
61
+ return {
62
+ remoteXPC: remoteXPC as RemoteXpcConnection,
63
+ mobileConfigService: new MobileConfigService([
64
+ tunnelConnection.host,
65
+ parseInt(mobileConfigService.port, 10),
66
+ ]),
67
+ };
68
+ }
52
69
  export async function startMobileImageMounterService(
53
70
  udid: string,
54
71
  ): Promise<MobileImageMounterServiceWithConnection> {