@appium/coresim 1.0.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.
Files changed (138) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +66 -0
  3. package/binding.gyp +53 -0
  4. package/lib/src/commands/app.d.ts +88 -0
  5. package/lib/src/commands/app.d.ts.map +1 -0
  6. package/lib/src/commands/app.js +133 -0
  7. package/lib/src/commands/app.js.map +1 -0
  8. package/lib/src/commands/biometric.d.ts +33 -0
  9. package/lib/src/commands/biometric.d.ts.map +1 -0
  10. package/lib/src/commands/biometric.js +44 -0
  11. package/lib/src/commands/biometric.js.map +1 -0
  12. package/lib/src/commands/darwin-notification.d.ts +36 -0
  13. package/lib/src/commands/darwin-notification.d.ts.map +1 -0
  14. package/lib/src/commands/darwin-notification.js +35 -0
  15. package/lib/src/commands/darwin-notification.js.map +1 -0
  16. package/lib/src/commands/interaction.d.ts +48 -0
  17. package/lib/src/commands/interaction.d.ts.map +1 -0
  18. package/lib/src/commands/interaction.js +48 -0
  19. package/lib/src/commands/interaction.js.map +1 -0
  20. package/lib/src/commands/keychain.d.ts +25 -0
  21. package/lib/src/commands/keychain.d.ts.map +1 -0
  22. package/lib/src/commands/keychain.js +52 -0
  23. package/lib/src/commands/keychain.js.map +1 -0
  24. package/lib/src/commands/lifecycle.d.ts +101 -0
  25. package/lib/src/commands/lifecycle.d.ts.map +1 -0
  26. package/lib/src/commands/lifecycle.js +165 -0
  27. package/lib/src/commands/lifecycle.js.map +1 -0
  28. package/lib/src/commands/media.d.ts +28 -0
  29. package/lib/src/commands/media.d.ts.map +1 -0
  30. package/lib/src/commands/media.js +27 -0
  31. package/lib/src/commands/media.js.map +1 -0
  32. package/lib/src/commands/misc.d.ts +15 -0
  33. package/lib/src/commands/misc.d.ts.map +1 -0
  34. package/lib/src/commands/misc.js +12 -0
  35. package/lib/src/commands/misc.js.map +1 -0
  36. package/lib/src/commands/pasteboard.d.ts +24 -0
  37. package/lib/src/commands/pasteboard.d.ts.map +1 -0
  38. package/lib/src/commands/pasteboard.js +22 -0
  39. package/lib/src/commands/pasteboard.js.map +1 -0
  40. package/lib/src/commands/permissions.d.ts +48 -0
  41. package/lib/src/commands/permissions.d.ts.map +1 -0
  42. package/lib/src/commands/permissions.js +84 -0
  43. package/lib/src/commands/permissions.js.map +1 -0
  44. package/lib/src/commands/process.d.ts +16 -0
  45. package/lib/src/commands/process.d.ts.map +1 -0
  46. package/lib/src/commands/process.js +68 -0
  47. package/lib/src/commands/process.js.map +1 -0
  48. package/lib/src/commands/screenshot.d.ts +29 -0
  49. package/lib/src/commands/screenshot.d.ts.map +1 -0
  50. package/lib/src/commands/screenshot.js +30 -0
  51. package/lib/src/commands/screenshot.js.map +1 -0
  52. package/lib/src/commands/spawn.d.ts +48 -0
  53. package/lib/src/commands/spawn.d.ts.map +1 -0
  54. package/lib/src/commands/spawn.js +108 -0
  55. package/lib/src/commands/spawn.js.map +1 -0
  56. package/lib/src/commands/ui.d.ts +42 -0
  57. package/lib/src/commands/ui.d.ts.map +1 -0
  58. package/lib/src/commands/ui.js +44 -0
  59. package/lib/src/commands/ui.js.map +1 -0
  60. package/lib/src/commands/webinspector.d.ts +19 -0
  61. package/lib/src/commands/webinspector.d.ts.map +1 -0
  62. package/lib/src/commands/webinspector.js +16 -0
  63. package/lib/src/commands/webinspector.js.map +1 -0
  64. package/lib/src/errors.d.ts +51 -0
  65. package/lib/src/errors.d.ts.map +1 -0
  66. package/lib/src/errors.js +82 -0
  67. package/lib/src/errors.js.map +1 -0
  68. package/lib/src/index.d.ts +7 -0
  69. package/lib/src/index.d.ts.map +1 -0
  70. package/lib/src/index.js +5 -0
  71. package/lib/src/index.js.map +1 -0
  72. package/lib/src/native-simctl.d.ts +62 -0
  73. package/lib/src/native-simctl.d.ts.map +1 -0
  74. package/lib/src/native-simctl.js +221 -0
  75. package/lib/src/native-simctl.js.map +1 -0
  76. package/lib/src/types.d.ts +267 -0
  77. package/lib/src/types.d.ts.map +1 -0
  78. package/lib/src/types.js +29 -0
  79. package/lib/src/types.js.map +1 -0
  80. package/lib/src/utils/index.d.ts +3 -0
  81. package/lib/src/utils/index.d.ts.map +1 -0
  82. package/lib/src/utils/index.js +3 -0
  83. package/lib/src/utils/index.js.map +1 -0
  84. package/lib/src/utils/pkg-root.d.ts +6 -0
  85. package/lib/src/utils/pkg-root.d.ts.map +1 -0
  86. package/lib/src/utils/pkg-root.js +12 -0
  87. package/lib/src/utils/pkg-root.js.map +1 -0
  88. package/lib/src/utils/run-catching.d.ts +3 -0
  89. package/lib/src/utils/run-catching.d.ts.map +1 -0
  90. package/lib/src/utils/run-catching.js +11 -0
  91. package/lib/src/utils/run-catching.js.map +1 -0
  92. package/package.json +73 -0
  93. package/scripts/install.mjs +22 -0
  94. package/src/commands/app.ts +186 -0
  95. package/src/commands/biometric.ts +69 -0
  96. package/src/commands/darwin-notification.ts +51 -0
  97. package/src/commands/interaction.ts +74 -0
  98. package/src/commands/keychain.ts +63 -0
  99. package/src/commands/lifecycle.ts +210 -0
  100. package/src/commands/media.ts +38 -0
  101. package/src/commands/misc.ts +20 -0
  102. package/src/commands/pasteboard.ts +31 -0
  103. package/src/commands/permissions.ts +122 -0
  104. package/src/commands/process.ts +80 -0
  105. package/src/commands/screenshot.ts +46 -0
  106. package/src/commands/spawn.ts +133 -0
  107. package/src/commands/ui.ts +61 -0
  108. package/src/commands/webinspector.ts +23 -0
  109. package/src/coresim.mm +1066 -0
  110. package/src/errors.ts +93 -0
  111. package/src/index.ts +23 -0
  112. package/src/native/async_bridge.h +164 -0
  113. package/src/native/nserror_bridge.h +64 -0
  114. package/src/native/nserror_bridge.mm +30 -0
  115. package/src/native/objc_runtime.h +45 -0
  116. package/src/native/objc_runtime.mm +76 -0
  117. package/src/native/safe_dispatch.h +38 -0
  118. package/src/native/sim_device.h +143 -0
  119. package/src/native/sim_device.mm +355 -0
  120. package/src/native/sim_device_set.h +16 -0
  121. package/src/native/sim_device_set.mm +40 -0
  122. package/src/native/sim_pasteboard.h +16 -0
  123. package/src/native/sim_pasteboard.mm +295 -0
  124. package/src/native/sim_process.h +13 -0
  125. package/src/native/sim_process.mm +139 -0
  126. package/src/native/sim_screenshot.h +28 -0
  127. package/src/native/sim_screenshot.mm +226 -0
  128. package/src/native/sim_service_context.h +42 -0
  129. package/src/native/sim_service_context.mm +92 -0
  130. package/src/native/tcc_privacy.h +35 -0
  131. package/src/native/tcc_privacy.mm +256 -0
  132. package/src/native/value_bridge.h +18 -0
  133. package/src/native/value_bridge.mm +111 -0
  134. package/src/native-simctl.ts +288 -0
  135. package/src/types.ts +302 -0
  136. package/src/utils/index.ts +2 -0
  137. package/src/utils/pkg-root.ts +14 -0
  138. package/src/utils/run-catching.ts +10 -0
@@ -0,0 +1,143 @@
1
+ #pragma once
2
+
3
+ #import <Foundation/Foundation.h>
4
+
5
+ namespace coresim {
6
+
7
+ // -[SimDevice UDID] / -[SimDevice name] / -[SimDevice state] / -[SimDevice deviceType] /
8
+ // -[SimDevice runtime]. `state` is the raw SimDeviceState enum value (0=Creating, 1=Shutdown,
9
+ // 2=Booting, 3=Booted, 4=ShuttingDown).
10
+ NSUUID* DeviceUDID(id device);
11
+ NSString* DeviceName(id device);
12
+ unsigned long long DeviceState(id device);
13
+ id DeviceDeviceType(id device);
14
+ id DeviceRuntime(id device);
15
+
16
+ // -[SimDevice dataPath] -> the device's `data` directory
17
+ // (~/Library/Developer/CoreSimulator/Devices/<udid>/data), the root of everything the guest OS
18
+ // considers its own filesystem (app containers, Library, etc.) — used to locate TCC.db for
19
+ // privacy-permission access (see tcc_privacy.h).
20
+ NSString* DeviceDataPath(id device);
21
+
22
+ // -[SimDevice bootWithOptions:error:]
23
+ BOOL Boot(id device, NSDictionary* options, NSError** error);
24
+
25
+ // -[SimDevice bootAsyncWithOptions:completionQueue:completionHandler:]. `handler` runs on `queue`
26
+ // exactly once with the resulting NSError (nil on success) — this is what replaces the CLI's
27
+ // bootstatus poll-until-timeout race.
28
+ void BootAsync(id device, NSDictionary* options, dispatch_queue_t queue, void (^handler)(NSError*));
29
+
30
+ // -[SimDevice bootStatus] -> SimDeviceBootInfo* describing the most recent boot attempt's
31
+ // progress, or nil if the device has never been booted. This is the same underlying mechanism
32
+ // `simctl bootstatus` itself uses — a separate, far more granular signal than SimDeviceState,
33
+ // tracking post-boot data migration and system-app readiness that `state` knows nothing about
34
+ // (see CLAUDE.md).
35
+ //
36
+ // Confirmed empirically NOT reset on shutdown: after `shutdownWithError:`, this still returns the
37
+ // *previous* boot session's terminal SimDeviceBootInfo rather than nil — callers must also check
38
+ // SimDevice.state to tell "genuinely mid-boot" from "shut down, remembering an old boot".
39
+ id DeviceBootStatus(id device);
40
+
41
+ // -[SimDeviceBootInfo status] -> raw status code. Confirmed values (see CLAUDE.md): 0 = Booting,
42
+ // 2 = WaitingOnDataMigration, 4 = WaitingOnSystemApp, 0xFFFFFFFF = Finished (the only terminal
43
+ // value observed). `simctl bootstatus`'s own output also names a WaitingOnBackboard phase whose
44
+ // numeric value wasn't observed in testing (not every boot passes through it) — treat any value other than
45
+ // the four confirmed above as "not yet terminal, keep waiting" rather than an error.
46
+ unsigned int BootInfoStatus(id bootInfo);
47
+
48
+ // -[SimDeviceBootInfo isTerminalStatus] -> whether this boot attempt has fully settled. Confirmed
49
+ // empirically to stay YES after shutdown, reflecting the previous session — see DeviceBootStatus.
50
+ BOOL BootInfoIsTerminal(id bootInfo);
51
+
52
+ // -[SimDevice shutdownWithError:]
53
+ BOOL Shutdown(id device, NSError** error);
54
+
55
+ // -[SimDevice eraseContentsAndSettingsWithError:]
56
+ BOOL Erase(id device, NSError** error);
57
+
58
+ // -[SimDevice getenv:error:]
59
+ NSString* Getenv(id device, NSString* name, NSError** error);
60
+
61
+ // -[SimDevice lookup:error:] -> a Mach port (0/MACH_PORT_NULL on failure), resolved within the
62
+ // device's own launchd_sim bootstrap namespace by name. Confirmed empirically (see CLAUDE.md) to
63
+ // need no special entitlement — used to reach the pasteboard sync service (sim_pasteboard.h),
64
+ // the same way Apple's own Simulator.app does.
65
+ unsigned int LookupMachPort(id device, NSString* serviceName, NSError** error);
66
+
67
+ // -[SimDevice installApplication:withOptions:error:]
68
+ BOOL InstallApp(id device, NSURL* appURL, NSDictionary* options, NSError** error);
69
+
70
+ // -[SimDevice uninstallApplication:withOptions:error:]
71
+ BOOL UninstallApp(id device, NSString* bundleID, NSDictionary* options, NSError** error);
72
+
73
+ // -[SimDevice launchApplicationWithID:options:error:]. Returns the launched pid.
74
+ int LaunchApp(id device, NSString* bundleID, NSDictionary* options, NSError** error);
75
+
76
+ // -[SimDevice terminateApplicationWithID:error:]
77
+ BOOL TerminateApp(id device, NSString* bundleID, NSError** error);
78
+
79
+ // -[SimDevice propertiesOfApplication:error:]
80
+ NSDictionary* PropertiesOfApplication(id device, NSString* bundleID, NSError** error);
81
+
82
+ // -[SimDevice installedAppsWithError:]
83
+ NSDictionary* InstalledApps(id device, NSError** error);
84
+
85
+ // -[SimDevice openURL:error:]
86
+ BOOL OpenURL(id device, NSURL* url, NSError** error);
87
+
88
+ // -[SimDevice(SimLocation) setLocationWithLatitude:andLongitude:error:]
89
+ BOOL SetLocation(id device, double latitude, double longitude, NSError** error);
90
+
91
+ // -[SimDevice(SimLocation) clearSimulatedLocationWithError:]
92
+ BOOL ClearLocation(id device, NSError** error);
93
+
94
+ // -[SimDevice(SimPushNotification) sendPushNotificationForBundleID:jsonPayload:error:] — despite
95
+ // the selector's "json" naming, the real parameter type is NSDictionary*, not NSData* (confirmed
96
+ // empirically: ObjC type encoding can't distinguish object *classes*, only that a parameter is
97
+ // some object pointer, so the original signature recovery guessed wrong; passing NSData crashes
98
+ // with "-[NSConcreteData objectForKeyedSubscript:]: unrecognized selector" regardless of whether
99
+ // the NSData holds JSON text or a serialized plist — see CLAUDE.md).
100
+ BOOL SendPushNotification(id device, NSString* bundleID, NSDictionary* payload, NSError** error);
101
+
102
+ // -[SimDevice(SimDeviceKeychain) addCertificateAtURL:trustAsRoot:error:]
103
+ BOOL AddCertificate(id device, NSURL* certURL, BOOL trustAsRoot, NSError** error);
104
+
105
+ // -[SimDevice(SimDeviceKeychain) resetKeychainWithError:]
106
+ BOOL ResetKeychain(id device, NSError** error);
107
+
108
+ // -[SimDevice(SimUIInterfaceStyle) currentUIInterfaceStyle] / setUIInterfaceStyle:error:
109
+ long long CurrentUIInterfaceStyle(id device);
110
+ BOOL SetUIInterfaceStyle(id device, long long style, NSError** error);
111
+
112
+ // -[SimDevice(Accessibility) currentIncreaseContrastMode] / setIncreaseContrastEnabled:error:
113
+ long long CurrentIncreaseContrastMode(id device);
114
+ BOOL SetIncreaseContrastEnabled(id device, BOOL enabled, NSError** error);
115
+
116
+ // -[SimDevice(Accessibility) currentContentSizeCategory] / setContentSizeCategory:error:
117
+ long long CurrentContentSizeCategory(id device);
118
+ BOOL SetContentSizeCategory(id device, long long category, NSError** error);
119
+
120
+ // -[SimDevice darwinNotificationGetState:name:error:]
121
+ BOOL DarwinNotificationGetState(id device, unsigned long long* outState, NSString* name, NSError** error);
122
+
123
+ // -[SimDevice darwinNotificationSetState:name:error:]
124
+ BOOL DarwinNotificationSetState(id device, unsigned long long state, NSString* name, NSError** error);
125
+
126
+ // -[SimDevice postDarwinNotification:error:]
127
+ BOOL PostDarwinNotification(id device, NSString* name, NSError** error);
128
+
129
+ // -[SimDevice spawnWithPath:options:terminationQueue:terminationHandler:error:]. Returns the
130
+ // spawned pid; `terminationHandler` runs on `terminationQueue` once with the exit status.
131
+ int Spawn(id device, NSString* path, NSDictionary* options, dispatch_queue_t terminationQueue,
132
+ void (^terminationHandler)(int), NSError** error);
133
+
134
+ // -[SimDevice addMedia:error:] — takes an array of file URLs (photos/videos), auto-detected by
135
+ // type; this is what `simctl addmedia`'s multi-path form calls into.
136
+ BOOL AddMedia(id device, NSArray<NSURL*>* fileURLs, NSError** error);
137
+
138
+ // -[SimDevice addPhoto:error:] / -[SimDevice addVideo:error:] — single-file convenience variants
139
+ // alongside AddMedia, for a caller that already knows which kind it's adding.
140
+ BOOL AddPhoto(id device, NSURL* fileURL, NSError** error);
141
+ BOOL AddVideo(id device, NSURL* fileURL, NSError** error);
142
+
143
+ } // namespace coresim
@@ -0,0 +1,355 @@
1
+ #include "sim_device.h"
2
+
3
+ #import <objc/message.h>
4
+
5
+ #include "objc_runtime.h"
6
+ #include "safe_dispatch.h"
7
+
8
+ namespace coresim {
9
+
10
+ namespace {
11
+
12
+ // Shared shapes reused across the many identical-signature getters/setters below.
13
+ id IdGetter(id target, const std::string& selectorName) {
14
+ RequireSelector(target, selectorName);
15
+ SEL selector = SelectorNamed(selectorName);
16
+ return SafeInvoke([&] {
17
+ using Fn = id (*)(id, SEL);
18
+ return ((Fn)objc_msgSend)(target, selector);
19
+ });
20
+ }
21
+
22
+ BOOL BoolWithError(id target, const std::string& selectorName, NSError** error) {
23
+ RequireSelector(target, selectorName);
24
+ SEL selector = SelectorNamed(selectorName);
25
+ return SafeInvoke([&] {
26
+ using Fn = BOOL (*)(id, SEL, NSError**);
27
+ return ((Fn)objc_msgSend)(target, selector, error);
28
+ });
29
+ }
30
+
31
+ BOOL BoolGetter(id target, const std::string& selectorName) {
32
+ RequireSelector(target, selectorName);
33
+ SEL selector = SelectorNamed(selectorName);
34
+ return SafeInvoke([&] {
35
+ using Fn = BOOL (*)(id, SEL);
36
+ return ((Fn)objc_msgSend)(target, selector);
37
+ });
38
+ }
39
+
40
+ unsigned int UIntGetter(id target, const std::string& selectorName) {
41
+ RequireSelector(target, selectorName);
42
+ SEL selector = SelectorNamed(selectorName);
43
+ return SafeInvoke([&] {
44
+ using Fn = unsigned int (*)(id, SEL);
45
+ return ((Fn)objc_msgSend)(target, selector);
46
+ });
47
+ }
48
+
49
+ } // namespace
50
+
51
+ NSUUID* DeviceUDID(id device) { return IdGetter(device, "UDID"); }
52
+ NSString* DeviceName(id device) { return IdGetter(device, "name"); }
53
+ id DeviceDeviceType(id device) { return IdGetter(device, "deviceType"); }
54
+ id DeviceRuntime(id device) { return IdGetter(device, "runtime"); }
55
+ NSString* DeviceDataPath(id device) { return IdGetter(device, "dataPath"); }
56
+
57
+ unsigned long long DeviceState(id device) {
58
+ static const std::string kSelectorName = "state";
59
+ RequireSelector(device, kSelectorName);
60
+ SEL selector = SelectorNamed(kSelectorName);
61
+ return SafeInvoke([&] {
62
+ using Fn = unsigned long long (*)(id, SEL);
63
+ return ((Fn)objc_msgSend)(device, selector);
64
+ });
65
+ }
66
+
67
+ BOOL Boot(id device, NSDictionary* options, NSError** error) {
68
+ static const std::string kSelectorName = "bootWithOptions:error:";
69
+ RequireSelector(device, kSelectorName);
70
+ SEL selector = SelectorNamed(kSelectorName);
71
+ return SafeInvoke([&] {
72
+ using Fn = BOOL (*)(id, SEL, NSDictionary*, NSError**);
73
+ return ((Fn)objc_msgSend)(device, selector, options, error);
74
+ });
75
+ }
76
+
77
+ void BootAsync(id device, NSDictionary* options, dispatch_queue_t queue, void (^handler)(NSError*)) {
78
+ static const std::string kSelectorName = "bootAsyncWithOptions:completionQueue:completionHandler:";
79
+ RequireSelector(device, kSelectorName);
80
+ SEL selector = SelectorNamed(kSelectorName);
81
+ SafeInvoke([&] {
82
+ using Fn = void (*)(id, SEL, NSDictionary*, dispatch_queue_t, void (^)(NSError*));
83
+ ((Fn)objc_msgSend)(device, selector, options, queue, handler);
84
+ return true;
85
+ });
86
+ }
87
+
88
+ id DeviceBootStatus(id device) { return IdGetter(device, "bootStatus"); }
89
+
90
+ unsigned int BootInfoStatus(id bootInfo) { return UIntGetter(bootInfo, "status"); }
91
+
92
+ BOOL BootInfoIsTerminal(id bootInfo) { return BoolGetter(bootInfo, "isTerminalStatus"); }
93
+
94
+ BOOL Shutdown(id device, NSError** error) { return BoolWithError(device, "shutdownWithError:", error); }
95
+
96
+ BOOL Erase(id device, NSError** error) { return BoolWithError(device, "eraseContentsAndSettingsWithError:", error); }
97
+
98
+ NSString* Getenv(id device, NSString* name, NSError** error) {
99
+ static const std::string kSelectorName = "getenv:error:";
100
+ RequireSelector(device, kSelectorName);
101
+ SEL selector = SelectorNamed(kSelectorName);
102
+ return SafeInvoke([&] {
103
+ using Fn = NSString* (*)(id, SEL, NSString*, NSError**);
104
+ return ((Fn)objc_msgSend)(device, selector, name, error);
105
+ });
106
+ }
107
+
108
+ unsigned int LookupMachPort(id device, NSString* serviceName, NSError** error) {
109
+ static const std::string kSelectorName = "lookup:error:";
110
+ RequireSelector(device, kSelectorName);
111
+ SEL selector = SelectorNamed(kSelectorName);
112
+ return SafeInvoke([&] {
113
+ using Fn = unsigned int (*)(id, SEL, NSString*, NSError**);
114
+ return ((Fn)objc_msgSend)(device, selector, serviceName, error);
115
+ });
116
+ }
117
+
118
+ BOOL InstallApp(id device, NSURL* appURL, NSDictionary* options, NSError** error) {
119
+ static const std::string kSelectorName = "installApplication:withOptions:error:";
120
+ RequireSelector(device, kSelectorName);
121
+ SEL selector = SelectorNamed(kSelectorName);
122
+ return SafeInvoke([&] {
123
+ using Fn = BOOL (*)(id, SEL, NSURL*, NSDictionary*, NSError**);
124
+ return ((Fn)objc_msgSend)(device, selector, appURL, options, error);
125
+ });
126
+ }
127
+
128
+ BOOL UninstallApp(id device, NSString* bundleID, NSDictionary* options, NSError** error) {
129
+ static const std::string kSelectorName = "uninstallApplication:withOptions:error:";
130
+ RequireSelector(device, kSelectorName);
131
+ SEL selector = SelectorNamed(kSelectorName);
132
+ return SafeInvoke([&] {
133
+ using Fn = BOOL (*)(id, SEL, NSString*, NSDictionary*, NSError**);
134
+ return ((Fn)objc_msgSend)(device, selector, bundleID, options, error);
135
+ });
136
+ }
137
+
138
+ int LaunchApp(id device, NSString* bundleID, NSDictionary* options, NSError** error) {
139
+ static const std::string kSelectorName = "launchApplicationWithID:options:error:";
140
+ RequireSelector(device, kSelectorName);
141
+ SEL selector = SelectorNamed(kSelectorName);
142
+ return SafeInvoke([&] {
143
+ using Fn = int (*)(id, SEL, NSString*, NSDictionary*, NSError**);
144
+ return ((Fn)objc_msgSend)(device, selector, bundleID, options, error);
145
+ });
146
+ }
147
+
148
+ BOOL TerminateApp(id device, NSString* bundleID, NSError** error) {
149
+ static const std::string kSelectorName = "terminateApplicationWithID:error:";
150
+ RequireSelector(device, kSelectorName);
151
+ SEL selector = SelectorNamed(kSelectorName);
152
+ return SafeInvoke([&] {
153
+ using Fn = BOOL (*)(id, SEL, NSString*, NSError**);
154
+ return ((Fn)objc_msgSend)(device, selector, bundleID, error);
155
+ });
156
+ }
157
+
158
+ NSDictionary* PropertiesOfApplication(id device, NSString* bundleID, NSError** error) {
159
+ static const std::string kSelectorName = "propertiesOfApplication:error:";
160
+ RequireSelector(device, kSelectorName);
161
+ SEL selector = SelectorNamed(kSelectorName);
162
+ return SafeInvoke([&] {
163
+ using Fn = NSDictionary* (*)(id, SEL, NSString*, NSError**);
164
+ return ((Fn)objc_msgSend)(device, selector, bundleID, error);
165
+ });
166
+ }
167
+
168
+ NSDictionary* InstalledApps(id device, NSError** error) {
169
+ static const std::string kSelectorName = "installedAppsWithError:";
170
+ RequireSelector(device, kSelectorName);
171
+ SEL selector = SelectorNamed(kSelectorName);
172
+ return SafeInvoke([&] {
173
+ using Fn = NSDictionary* (*)(id, SEL, NSError**);
174
+ return ((Fn)objc_msgSend)(device, selector, error);
175
+ });
176
+ }
177
+
178
+ BOOL OpenURL(id device, NSURL* url, NSError** error) {
179
+ static const std::string kSelectorName = "openURL:error:";
180
+ RequireSelector(device, kSelectorName);
181
+ SEL selector = SelectorNamed(kSelectorName);
182
+ return SafeInvoke([&] {
183
+ using Fn = BOOL (*)(id, SEL, NSURL*, NSError**);
184
+ return ((Fn)objc_msgSend)(device, selector, url, error);
185
+ });
186
+ }
187
+
188
+ BOOL SetLocation(id device, double latitude, double longitude, NSError** error) {
189
+ static const std::string kSelectorName = "setLocationWithLatitude:andLongitude:error:";
190
+ RequireSelector(device, kSelectorName);
191
+ SEL selector = SelectorNamed(kSelectorName);
192
+ return SafeInvoke([&] {
193
+ using Fn = BOOL (*)(id, SEL, double, double, NSError**);
194
+ return ((Fn)objc_msgSend)(device, selector, latitude, longitude, error);
195
+ });
196
+ }
197
+
198
+ BOOL ClearLocation(id device, NSError** error) {
199
+ return BoolWithError(device, "clearSimulatedLocationWithError:", error);
200
+ }
201
+
202
+ BOOL SendPushNotification(id device, NSString* bundleID, NSDictionary* payload, NSError** error) {
203
+ static const std::string kSelectorName = "sendPushNotificationForBundleID:jsonPayload:error:";
204
+ RequireSelector(device, kSelectorName);
205
+ SEL selector = SelectorNamed(kSelectorName);
206
+ return SafeInvoke([&] {
207
+ using Fn = BOOL (*)(id, SEL, NSString*, NSDictionary*, NSError**);
208
+ return ((Fn)objc_msgSend)(device, selector, bundleID, payload, error);
209
+ });
210
+ }
211
+
212
+ BOOL AddCertificate(id device, NSURL* certURL, BOOL trustAsRoot, NSError** error) {
213
+ static const std::string kSelectorName = "addCertificateAtURL:trustAsRoot:error:";
214
+ RequireSelector(device, kSelectorName);
215
+ SEL selector = SelectorNamed(kSelectorName);
216
+ return SafeInvoke([&] {
217
+ using Fn = BOOL (*)(id, SEL, NSURL*, BOOL, NSError**);
218
+ return ((Fn)objc_msgSend)(device, selector, certURL, trustAsRoot, error);
219
+ });
220
+ }
221
+
222
+ BOOL ResetKeychain(id device, NSError** error) { return BoolWithError(device, "resetKeychainWithError:", error); }
223
+
224
+ long long CurrentUIInterfaceStyle(id device) {
225
+ static const std::string kSelectorName = "currentUIInterfaceStyle";
226
+ RequireSelector(device, kSelectorName);
227
+ SEL selector = SelectorNamed(kSelectorName);
228
+ return SafeInvoke([&] {
229
+ using Fn = long long (*)(id, SEL);
230
+ return ((Fn)objc_msgSend)(device, selector);
231
+ });
232
+ }
233
+
234
+ BOOL SetUIInterfaceStyle(id device, long long style, NSError** error) {
235
+ static const std::string kSelectorName = "setUIInterfaceStyle:error:";
236
+ RequireSelector(device, kSelectorName);
237
+ SEL selector = SelectorNamed(kSelectorName);
238
+ return SafeInvoke([&] {
239
+ using Fn = BOOL (*)(id, SEL, long long, NSError**);
240
+ return ((Fn)objc_msgSend)(device, selector, style, error);
241
+ });
242
+ }
243
+
244
+ long long CurrentIncreaseContrastMode(id device) {
245
+ static const std::string kSelectorName = "currentIncreaseContrastMode";
246
+ RequireSelector(device, kSelectorName);
247
+ SEL selector = SelectorNamed(kSelectorName);
248
+ return SafeInvoke([&] {
249
+ using Fn = long long (*)(id, SEL);
250
+ return ((Fn)objc_msgSend)(device, selector);
251
+ });
252
+ }
253
+
254
+ BOOL SetIncreaseContrastEnabled(id device, BOOL enabled, NSError** error) {
255
+ static const std::string kSelectorName = "setIncreaseContrastEnabled:error:";
256
+ RequireSelector(device, kSelectorName);
257
+ SEL selector = SelectorNamed(kSelectorName);
258
+ return SafeInvoke([&] {
259
+ using Fn = BOOL (*)(id, SEL, BOOL, NSError**);
260
+ return ((Fn)objc_msgSend)(device, selector, enabled, error);
261
+ });
262
+ }
263
+
264
+ long long CurrentContentSizeCategory(id device) {
265
+ static const std::string kSelectorName = "currentContentSizeCategory";
266
+ RequireSelector(device, kSelectorName);
267
+ SEL selector = SelectorNamed(kSelectorName);
268
+ return SafeInvoke([&] {
269
+ using Fn = long long (*)(id, SEL);
270
+ return ((Fn)objc_msgSend)(device, selector);
271
+ });
272
+ }
273
+
274
+ BOOL SetContentSizeCategory(id device, long long category, NSError** error) {
275
+ static const std::string kSelectorName = "setContentSizeCategory:error:";
276
+ RequireSelector(device, kSelectorName);
277
+ SEL selector = SelectorNamed(kSelectorName);
278
+ return SafeInvoke([&] {
279
+ using Fn = BOOL (*)(id, SEL, long long, NSError**);
280
+ return ((Fn)objc_msgSend)(device, selector, category, error);
281
+ });
282
+ }
283
+
284
+ BOOL DarwinNotificationGetState(id device, unsigned long long* outState, NSString* name, NSError** error) {
285
+ static const std::string kSelectorName = "darwinNotificationGetState:name:error:";
286
+ RequireSelector(device, kSelectorName);
287
+ SEL selector = SelectorNamed(kSelectorName);
288
+ return SafeInvoke([&] {
289
+ using Fn = BOOL (*)(id, SEL, unsigned long long*, NSString*, NSError**);
290
+ return ((Fn)objc_msgSend)(device, selector, outState, name, error);
291
+ });
292
+ }
293
+
294
+ BOOL DarwinNotificationSetState(id device, unsigned long long state, NSString* name, NSError** error) {
295
+ static const std::string kSelectorName = "darwinNotificationSetState:name:error:";
296
+ RequireSelector(device, kSelectorName);
297
+ SEL selector = SelectorNamed(kSelectorName);
298
+ return SafeInvoke([&] {
299
+ using Fn = BOOL (*)(id, SEL, unsigned long long, NSString*, NSError**);
300
+ return ((Fn)objc_msgSend)(device, selector, state, name, error);
301
+ });
302
+ }
303
+
304
+ BOOL PostDarwinNotification(id device, NSString* name, NSError** error) {
305
+ static const std::string kSelectorName = "postDarwinNotification:error:";
306
+ RequireSelector(device, kSelectorName);
307
+ SEL selector = SelectorNamed(kSelectorName);
308
+ return SafeInvoke([&] {
309
+ using Fn = BOOL (*)(id, SEL, NSString*, NSError**);
310
+ return ((Fn)objc_msgSend)(device, selector, name, error);
311
+ });
312
+ }
313
+
314
+ int Spawn(id device, NSString* path, NSDictionary* options, dispatch_queue_t terminationQueue,
315
+ void (^terminationHandler)(int), NSError** error) {
316
+ static const std::string kSelectorName = "spawnWithPath:options:terminationQueue:terminationHandler:error:";
317
+ RequireSelector(device, kSelectorName);
318
+ SEL selector = SelectorNamed(kSelectorName);
319
+ return SafeInvoke([&] {
320
+ using Fn = int (*)(id, SEL, NSString*, NSDictionary*, dispatch_queue_t, void (^)(int), NSError**);
321
+ return ((Fn)objc_msgSend)(device, selector, path, options, terminationQueue, terminationHandler, error);
322
+ });
323
+ }
324
+
325
+ BOOL AddMedia(id device, NSArray<NSURL*>* fileURLs, NSError** error) {
326
+ static const std::string kSelectorName = "addMedia:error:";
327
+ RequireSelector(device, kSelectorName);
328
+ SEL selector = SelectorNamed(kSelectorName);
329
+ return SafeInvoke([&] {
330
+ using Fn = BOOL (*)(id, SEL, NSArray<NSURL*>*, NSError**);
331
+ return ((Fn)objc_msgSend)(device, selector, fileURLs, error);
332
+ });
333
+ }
334
+
335
+ BOOL AddPhoto(id device, NSURL* fileURL, NSError** error) {
336
+ static const std::string kSelectorName = "addPhoto:error:";
337
+ RequireSelector(device, kSelectorName);
338
+ SEL selector = SelectorNamed(kSelectorName);
339
+ return SafeInvoke([&] {
340
+ using Fn = BOOL (*)(id, SEL, NSURL*, NSError**);
341
+ return ((Fn)objc_msgSend)(device, selector, fileURL, error);
342
+ });
343
+ }
344
+
345
+ BOOL AddVideo(id device, NSURL* fileURL, NSError** error) {
346
+ static const std::string kSelectorName = "addVideo:error:";
347
+ RequireSelector(device, kSelectorName);
348
+ SEL selector = SelectorNamed(kSelectorName);
349
+ return SafeInvoke([&] {
350
+ using Fn = BOOL (*)(id, SEL, NSURL*, NSError**);
351
+ return ((Fn)objc_msgSend)(device, selector, fileURL, error);
352
+ });
353
+ }
354
+
355
+ } // namespace coresim
@@ -0,0 +1,16 @@
1
+ #pragma once
2
+
3
+ #import <Foundation/Foundation.h>
4
+
5
+ namespace coresim {
6
+
7
+ // -[SimDeviceSet devices] -> NSArray<SimDevice*>
8
+ NSArray* Devices(id deviceSet);
9
+
10
+ // -[SimDeviceSet createDeviceWithType:runtime:name:error:]
11
+ id CreateDevice(id deviceSet, id deviceType, id runtime, NSString* name, NSError** error);
12
+
13
+ // -[SimDeviceSet deleteDevice:error:]
14
+ BOOL DeleteDevice(id deviceSet, id device, NSError** error);
15
+
16
+ } // namespace coresim
@@ -0,0 +1,40 @@
1
+ #include "sim_device_set.h"
2
+
3
+ #import <objc/message.h>
4
+
5
+ #include "objc_runtime.h"
6
+ #include "safe_dispatch.h"
7
+
8
+ namespace coresim {
9
+
10
+ NSArray* Devices(id deviceSet) {
11
+ static const std::string kSelectorName = "devices";
12
+ RequireSelector(deviceSet, kSelectorName);
13
+ SEL selector = SelectorNamed(kSelectorName);
14
+ return SafeInvoke([&] {
15
+ using Fn = NSArray* (*)(id, SEL);
16
+ return ((Fn)objc_msgSend)(deviceSet, selector);
17
+ });
18
+ }
19
+
20
+ id CreateDevice(id deviceSet, id deviceType, id runtime, NSString* name, NSError** error) {
21
+ static const std::string kSelectorName = "createDeviceWithType:runtime:name:error:";
22
+ RequireSelector(deviceSet, kSelectorName);
23
+ SEL selector = SelectorNamed(kSelectorName);
24
+ return SafeInvoke([&] {
25
+ using Fn = id (*)(id, SEL, id, id, NSString*, NSError**);
26
+ return ((Fn)objc_msgSend)(deviceSet, selector, deviceType, runtime, name, error);
27
+ });
28
+ }
29
+
30
+ BOOL DeleteDevice(id deviceSet, id device, NSError** error) {
31
+ static const std::string kSelectorName = "deleteDevice:error:";
32
+ RequireSelector(deviceSet, kSelectorName);
33
+ SEL selector = SelectorNamed(kSelectorName);
34
+ return SafeInvoke([&] {
35
+ using Fn = BOOL (*)(id, SEL, id, NSError**);
36
+ return ((Fn)objc_msgSend)(deviceSet, selector, device, error);
37
+ });
38
+ }
39
+
40
+ } // namespace coresim
@@ -0,0 +1,16 @@
1
+ #pragma once
2
+
3
+ #import <Foundation/Foundation.h>
4
+
5
+ namespace coresim {
6
+
7
+ // Reads the device's current pasteboard content, picking between two private mechanisms at
8
+ // runtime depending on which one's classes actually exist (see sim_pasteboard.mm). Throws
9
+ // NativeSimUnavailableError if neither is present. Returns "" (not nil) for an empty pasteboard,
10
+ // matching `simctl pbpaste`.
11
+ NSString* PullPasteboardString(id device, NSError** error);
12
+
13
+ // Writes `content` as the device's pasteboard content, via the same mechanism selection.
14
+ BOOL PushPasteboardString(id device, NSString* content, NSError** error);
15
+
16
+ } // namespace coresim