@efffrida/frida-tools 0.0.14 → 0.0.15
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/README.md +6 -10
- package/dist/{dts/FridaDevice.d.ts → FridaDevice.d.ts} +48 -4
- package/dist/FridaDevice.d.ts.map +1 -0
- package/dist/{esm/FridaDevice.js → FridaDevice.js} +22 -2
- package/dist/FridaDevice.js.map +1 -0
- package/dist/{dts/FridaDeviceAcquisitionError.d.ts → FridaDeviceAcquisitionError.d.ts} +2 -1
- package/dist/FridaDeviceAcquisitionError.d.ts.map +1 -0
- package/dist/{esm/FridaDeviceAcquisitionError.js → FridaDeviceAcquisitionError.js} +5 -1
- package/dist/FridaDeviceAcquisitionError.js.map +1 -0
- package/dist/FridaScript.d.ts +96 -0
- package/dist/FridaScript.d.ts.map +1 -0
- package/dist/FridaScript.js.map +1 -0
- package/dist/FridaSession.d.ts +72 -0
- package/dist/FridaSession.d.ts.map +1 -0
- package/dist/{esm/FridaSession.js → FridaSession.js} +10 -0
- package/dist/FridaSession.js.map +1 -0
- package/dist/FridaSessionError.d.ts.map +1 -0
- package/dist/FridaSessionError.js.map +1 -0
- package/dist/{dts/index.d.ts → index.d.ts} +8 -5
- package/dist/index.d.ts.map +1 -0
- package/dist/{esm/index.js → index.js} +3 -0
- package/dist/index.js.map +1 -0
- package/dist/{dts/internal → internal}/device.d.ts.map +1 -1
- package/dist/internal/device.js +189 -0
- package/dist/internal/device.js.map +1 -0
- package/dist/{dts/internal → internal}/script.d.ts.map +1 -1
- package/dist/internal/script.js +221 -0
- package/dist/internal/script.js.map +1 -0
- package/dist/{dts/internal → internal}/session.d.ts.map +1 -1
- package/dist/internal/session.js +124 -0
- package/dist/internal/session.js.map +1 -0
- package/package.json +54 -68
- package/src/FridaDevice.ts +92 -8
- package/src/FridaDeviceAcquisitionError.ts +6 -2
- package/src/FridaScript.ts +53 -31
- package/src/FridaSession.ts +31 -5
- package/src/FridaSessionError.ts +1 -1
- package/src/index.ts +9 -5
- package/src/internal/device.ts +311 -32
- package/src/internal/script.ts +265 -118
- package/src/internal/session.ts +135 -27
- package/FridaDevice/package.json +0 -6
- package/FridaDeviceAcquisitionError/package.json +0 -6
- package/FridaScript/package.json +0 -6
- package/FridaSession/package.json +0 -6
- package/FridaSessionError/package.json +0 -6
- package/dist/cjs/FridaDevice.js +0 -60
- package/dist/cjs/FridaDevice.js.map +0 -1
- package/dist/cjs/FridaDeviceAcquisitionError.js +0 -33
- package/dist/cjs/FridaDeviceAcquisitionError.js.map +0 -1
- package/dist/cjs/FridaScript.js +0 -40
- package/dist/cjs/FridaScript.js.map +0 -1
- package/dist/cjs/FridaSession.js +0 -45
- package/dist/cjs/FridaSession.js.map +0 -1
- package/dist/cjs/FridaSessionError.js +0 -37
- package/dist/cjs/FridaSessionError.js.map +0 -1
- package/dist/cjs/index.js +0 -18
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/internal/device.js +0 -68
- package/dist/cjs/internal/device.js.map +0 -1
- package/dist/cjs/internal/script.js +0 -163
- package/dist/cjs/internal/script.js.map +0 -1
- package/dist/cjs/internal/session.js +0 -55
- package/dist/cjs/internal/session.js.map +0 -1
- package/dist/dts/FridaDevice.d.ts.map +0 -1
- package/dist/dts/FridaDeviceAcquisitionError.d.ts.map +0 -1
- package/dist/dts/FridaScript.d.ts +0 -80
- package/dist/dts/FridaScript.d.ts.map +0 -1
- package/dist/dts/FridaSession.d.ts +0 -56
- package/dist/dts/FridaSession.d.ts.map +0 -1
- package/dist/dts/FridaSessionError.d.ts.map +0 -1
- package/dist/dts/index.d.ts.map +0 -1
- package/dist/esm/FridaDevice.js.map +0 -1
- package/dist/esm/FridaDeviceAcquisitionError.js.map +0 -1
- package/dist/esm/FridaScript.js.map +0 -1
- package/dist/esm/FridaSession.js.map +0 -1
- package/dist/esm/FridaSessionError.js.map +0 -1
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/internal/device.js +0 -55
- package/dist/esm/internal/device.js.map +0 -1
- package/dist/esm/internal/script.js +0 -155
- package/dist/esm/internal/script.js.map +0 -1
- package/dist/esm/internal/session.js +0 -44
- package/dist/esm/internal/session.js.map +0 -1
- package/dist/esm/package.json +0 -4
- package/index/package.json +0 -6
- /package/dist/{esm/FridaScript.js → FridaScript.js} +0 -0
- /package/dist/{dts/FridaSessionError.d.ts → FridaSessionError.d.ts} +0 -0
- /package/dist/{esm/FridaSessionError.js → FridaSessionError.js} +0 -0
- /package/dist/{dts/internal → internal}/device.d.ts +0 -0
- /package/dist/{dts/internal → internal}/script.d.ts +0 -0
- /package/dist/{dts/internal → internal}/session.d.ts +0 -0
package/src/internal/device.ts
CHANGED
|
@@ -1,11 +1,26 @@
|
|
|
1
|
-
import type * as
|
|
1
|
+
import type * as CommandExecutor from "@effect/platform/CommandExecutor";
|
|
2
|
+
import type * as ConfigError from "effect/ConfigError";
|
|
3
|
+
import type * as Scope from "effect/Scope";
|
|
4
|
+
import type * as FridaDevice from "../FridaDevice.ts";
|
|
2
5
|
|
|
6
|
+
import * as Command from "@effect/platform/Command";
|
|
7
|
+
import * as PlatformError from "@effect/platform/Error";
|
|
8
|
+
import * as Chunk from "effect/Chunk";
|
|
9
|
+
import * as Config from "effect/Config";
|
|
3
10
|
import * as Context from "effect/Context";
|
|
4
11
|
import * as Effect from "effect/Effect";
|
|
5
12
|
import * as Layer from "effect/Layer";
|
|
13
|
+
import * as ParseResult from "effect/ParseResult";
|
|
6
14
|
import * as Predicate from "effect/Predicate";
|
|
15
|
+
import * as Schema from "effect/Schema";
|
|
16
|
+
import * as Stream from "effect/Stream";
|
|
17
|
+
import * as String from "effect/String";
|
|
18
|
+
import * as Tuple from "effect/Tuple";
|
|
7
19
|
import * as Frida from "frida";
|
|
8
|
-
import * as
|
|
20
|
+
import * as net from "node:net";
|
|
21
|
+
import * as path from "node:path";
|
|
22
|
+
|
|
23
|
+
import * as FridaDeviceAcquisitionError from "../FridaDeviceAcquisitionError.ts";
|
|
9
24
|
|
|
10
25
|
/** @internal */
|
|
11
26
|
export const FridaDeviceTypeId: FridaDevice.FridaDeviceTypeId = Symbol.for(
|
|
@@ -19,65 +34,302 @@ export const Tag = Context.GenericTag<FridaDevice.FridaDevice>("@efffrida/frida-
|
|
|
19
34
|
export const isFridaDevice = (u: unknown): u is FridaDevice.FridaDevice => Predicate.hasProperty(u, FridaDeviceTypeId);
|
|
20
35
|
|
|
21
36
|
/** @internal */
|
|
22
|
-
export const
|
|
23
|
-
|
|
24
|
-
|
|
37
|
+
export const acquireLocalDevice = (): Effect.Effect<
|
|
38
|
+
FridaDevice.FridaDevice,
|
|
39
|
+
FridaDeviceAcquisitionError.FridaDeviceAcquisitionError,
|
|
40
|
+
never
|
|
41
|
+
> =>
|
|
25
42
|
Effect.map(
|
|
26
43
|
Effect.tryPromise({
|
|
27
|
-
try: () =>
|
|
44
|
+
try: (signal) => {
|
|
45
|
+
const cancellable = new Frida.Cancellable();
|
|
46
|
+
signal.onabort = () => cancellable.cancel();
|
|
47
|
+
return Frida.getLocalDevice(cancellable);
|
|
48
|
+
},
|
|
28
49
|
catch: (cause) =>
|
|
29
50
|
new FridaDeviceAcquisitionError.FridaDeviceAcquisitionError({
|
|
30
51
|
cause,
|
|
31
52
|
attempts: 1,
|
|
32
|
-
acquisitionMethod: "
|
|
53
|
+
acquisitionMethod: "local",
|
|
33
54
|
}),
|
|
34
55
|
}),
|
|
35
|
-
(device) =>
|
|
56
|
+
(device) =>
|
|
57
|
+
({
|
|
58
|
+
device,
|
|
59
|
+
host: "local://",
|
|
60
|
+
[FridaDeviceTypeId]: FridaDeviceTypeId,
|
|
61
|
+
}) as const
|
|
36
62
|
);
|
|
37
63
|
|
|
38
64
|
/** @internal */
|
|
39
|
-
export const
|
|
40
|
-
|
|
41
|
-
options?: Frida.RemoteDeviceOptions | undefined
|
|
65
|
+
export const acquireUsbDevice = (
|
|
66
|
+
options?: Frida.GetDeviceOptions | undefined
|
|
42
67
|
): Effect.Effect<FridaDevice.FridaDevice, FridaDeviceAcquisitionError.FridaDeviceAcquisitionError, never> =>
|
|
43
68
|
Effect.map(
|
|
44
69
|
Effect.tryPromise({
|
|
45
|
-
try: () =>
|
|
70
|
+
try: (signal) => {
|
|
71
|
+
const cancellable = new Frida.Cancellable();
|
|
72
|
+
signal.onabort = () => cancellable.cancel();
|
|
73
|
+
return Frida.getUsbDevice(options, cancellable);
|
|
74
|
+
},
|
|
46
75
|
catch: (cause) =>
|
|
47
76
|
new FridaDeviceAcquisitionError.FridaDeviceAcquisitionError({
|
|
48
77
|
cause,
|
|
49
78
|
attempts: 1,
|
|
50
|
-
acquisitionMethod: "
|
|
79
|
+
acquisitionMethod: "usb",
|
|
51
80
|
}),
|
|
52
81
|
}),
|
|
53
|
-
(device) =>
|
|
82
|
+
(device) =>
|
|
83
|
+
({
|
|
84
|
+
device,
|
|
85
|
+
host: "usb://",
|
|
86
|
+
[FridaDeviceTypeId]: FridaDeviceTypeId,
|
|
87
|
+
}) as const
|
|
54
88
|
);
|
|
55
89
|
|
|
56
90
|
/** @internal */
|
|
57
|
-
export const
|
|
91
|
+
export const acquireRemoteDevice = (
|
|
92
|
+
address: string,
|
|
93
|
+
options?: Frida.RemoteDeviceOptions | undefined
|
|
94
|
+
): Effect.Effect<FridaDevice.FridaDevice, FridaDeviceAcquisitionError.FridaDeviceAcquisitionError, Scope.Scope> => {
|
|
95
|
+
const acquire = Effect.tryPromise({
|
|
96
|
+
try: (signal) => {
|
|
97
|
+
const cancellable = new Frida.Cancellable();
|
|
98
|
+
signal.onabort = () => cancellable.cancel();
|
|
99
|
+
return Frida.getDeviceManager().addRemoteDevice(address, options, cancellable);
|
|
100
|
+
},
|
|
101
|
+
catch: (cause) =>
|
|
102
|
+
new FridaDeviceAcquisitionError.FridaDeviceAcquisitionError({
|
|
103
|
+
cause,
|
|
104
|
+
attempts: 1,
|
|
105
|
+
acquisitionMethod: "remote",
|
|
106
|
+
}),
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const release = (_device: Frida.Device) =>
|
|
110
|
+
Effect.promise((signal) => {
|
|
111
|
+
const cancellable = new Frida.Cancellable();
|
|
112
|
+
signal.onabort = () => cancellable.cancel();
|
|
113
|
+
return Frida.getDeviceManager().removeRemoteDevice(address, cancellable);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const resource = Effect.acquireRelease(acquire, release);
|
|
117
|
+
|
|
118
|
+
return Effect.map(
|
|
119
|
+
resource,
|
|
120
|
+
(device) =>
|
|
121
|
+
({
|
|
122
|
+
device,
|
|
123
|
+
host: `remote://${address}`,
|
|
124
|
+
[FridaDeviceTypeId]: FridaDeviceTypeId,
|
|
125
|
+
}) as const
|
|
126
|
+
);
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/** @internal */
|
|
130
|
+
export const acquireAndroidEmulatorDevice = Effect.fn("acquireAndroidEmulatorDevice")(
|
|
131
|
+
function* (
|
|
132
|
+
name: string,
|
|
133
|
+
options?:
|
|
134
|
+
| {
|
|
135
|
+
hidden?: boolean | undefined;
|
|
136
|
+
adbExecutable?: string | undefined;
|
|
137
|
+
fridaExecutable?: string | undefined;
|
|
138
|
+
emulatorExecutable?: string | undefined;
|
|
139
|
+
extraEmulatorArgs?: Array<string> | undefined;
|
|
140
|
+
}
|
|
141
|
+
| undefined
|
|
142
|
+
) {
|
|
143
|
+
const hidden = options?.hidden ?? false;
|
|
144
|
+
const adbExecutable = options?.adbExecutable ?? "adb";
|
|
145
|
+
const emulatorExecutable = options?.emulatorExecutable ?? "emulator";
|
|
146
|
+
const fridaExecutable = options?.fridaExecutable ?? "/data/local/tmp/frida-server";
|
|
147
|
+
|
|
148
|
+
yield* Effect.annotateCurrentSpan({
|
|
149
|
+
"emulator.name": name,
|
|
150
|
+
"emulator.hidden": hidden,
|
|
151
|
+
"adb.path": adbExecutable,
|
|
152
|
+
"frida.path": fridaExecutable,
|
|
153
|
+
"emulator.path": emulatorExecutable,
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const getTwoConsecutiveFreePorts = (startingAt: number = 2000) =>
|
|
157
|
+
Effect.async<readonly [firstPort: number, secondPort: number], never, never>((resume) => {
|
|
158
|
+
const socket1 = net.createConnection(startingAt);
|
|
159
|
+
const socket2 = net.createConnection(startingAt + 1);
|
|
160
|
+
|
|
161
|
+
const cleanup = () => {
|
|
162
|
+
socket1.removeAllListeners();
|
|
163
|
+
socket2.removeAllListeners();
|
|
164
|
+
socket1.destroy();
|
|
165
|
+
socket2.destroy();
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const onError = (error: NodeJS.ErrnoException) => {
|
|
169
|
+
if (error.code !== "ECONNREFUSED") {
|
|
170
|
+
resume(Effect.dieMessage("Failed to get two free consecutive ports"));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (socket1.connecting === false && socket2.connecting === false) {
|
|
174
|
+
cleanup();
|
|
175
|
+
resume(Effect.succeed(Tuple.make(startingAt, startingAt + 1)));
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const onConnect = () => {
|
|
180
|
+
cleanup();
|
|
181
|
+
resume(getTwoConsecutiveFreePorts(startingAt + 1));
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
socket1.once("error", onError);
|
|
185
|
+
socket2.once("error", onError);
|
|
186
|
+
socket1.once("connect", onConnect);
|
|
187
|
+
socket2.once("connect", onConnect);
|
|
188
|
+
return Effect.sync(() => cleanup());
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
const filterExitOk = (code: number) => (code === 0 ? Effect.void : Effect.fail(code));
|
|
192
|
+
|
|
193
|
+
const [firstPort, _secondPort] = yield* getTwoConsecutiveFreePorts();
|
|
194
|
+
const emulator = `emulator-${firstPort}`;
|
|
195
|
+
|
|
196
|
+
const emulatorProcess = yield* Command.make(
|
|
197
|
+
emulatorExecutable,
|
|
198
|
+
`@${name}`,
|
|
199
|
+
"-delay-adb",
|
|
200
|
+
"-read-only",
|
|
201
|
+
"-no-snapshot-save",
|
|
202
|
+
"-port",
|
|
203
|
+
firstPort.toString(),
|
|
204
|
+
...(hidden ? ["-no-window"] : []),
|
|
205
|
+
...(options?.extraEmulatorArgs ?? [])
|
|
206
|
+
).pipe(Command.start);
|
|
207
|
+
|
|
208
|
+
yield* Effect.addFinalizer(() =>
|
|
209
|
+
Command.make(adbExecutable, "-s", emulator, "emu", "kill")
|
|
210
|
+
.pipe(Command.exitCode)
|
|
211
|
+
.pipe(Effect.flatMap(filterExitOk))
|
|
212
|
+
.pipe(Effect.orDie)
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
const isBootCompletedPredicate = Predicate.or(
|
|
216
|
+
String.includes("Successfully loaded"),
|
|
217
|
+
String.includes("Boot completed")
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
const decoder = new TextDecoder();
|
|
221
|
+
yield* emulatorProcess.stderr.pipe(Stream.runHead).pipe(Effect.forkScoped);
|
|
222
|
+
yield* emulatorProcess.stdout
|
|
223
|
+
.pipe(Stream.mapChunks(Chunk.map((bytes) => decoder.decode(bytes))))
|
|
224
|
+
.pipe(Stream.splitLines)
|
|
225
|
+
.pipe(Stream.takeUntil(isBootCompletedPredicate))
|
|
226
|
+
.pipe(Stream.runDrain);
|
|
227
|
+
|
|
228
|
+
yield* Command.make(adbExecutable, `-s`, emulator, "wait-for-device")
|
|
229
|
+
.pipe(Command.exitCode)
|
|
230
|
+
.pipe(Effect.flatMap(filterExitOk))
|
|
231
|
+
.pipe(
|
|
232
|
+
Effect.mapError(
|
|
233
|
+
(code) =>
|
|
234
|
+
new FridaDeviceAcquisitionError.FridaDeviceAcquisitionError({
|
|
235
|
+
attempts: 1,
|
|
236
|
+
acquisitionMethod: "android-emulator",
|
|
237
|
+
cause: new Error(`ADB wait-for-device failed with exit code ${code}`),
|
|
238
|
+
})
|
|
239
|
+
)
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
yield* Command.make(adbExecutable, `-s`, emulator, "root")
|
|
243
|
+
.pipe(Command.exitCode)
|
|
244
|
+
.pipe(Effect.flatMap(filterExitOk))
|
|
245
|
+
.pipe(
|
|
246
|
+
Effect.mapError(
|
|
247
|
+
(code) =>
|
|
248
|
+
new FridaDeviceAcquisitionError.FridaDeviceAcquisitionError({
|
|
249
|
+
attempts: 1,
|
|
250
|
+
acquisitionMethod: "android-emulator",
|
|
251
|
+
cause: new Error(`ADB root failed with exit code ${code}`),
|
|
252
|
+
})
|
|
253
|
+
)
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
yield* Command.make(adbExecutable, "-s", emulator, "shell", `"${fridaExecutable}"`)
|
|
257
|
+
.pipe(Command.start)
|
|
258
|
+
.pipe(Effect.andThen(Effect.sleep("3 seconds")));
|
|
259
|
+
|
|
260
|
+
const fridaPort = yield* Command.make(adbExecutable, "-s", emulator, "forward", "tcp:0", "tcp:27042")
|
|
261
|
+
.pipe(Command.string)
|
|
262
|
+
.pipe(Effect.flatMap(Schema.decode(Schema.NumberFromString)));
|
|
263
|
+
|
|
264
|
+
const { host: _host, ...remoteDevice } = yield* acquireRemoteDevice(`localhost:${fridaPort}`);
|
|
265
|
+
|
|
266
|
+
return {
|
|
267
|
+
...remoteDevice,
|
|
268
|
+
host: `android-emulator://${emulator}`,
|
|
269
|
+
} as const;
|
|
270
|
+
},
|
|
271
|
+
Effect.timeoutFail({
|
|
272
|
+
duration: "1 minute",
|
|
273
|
+
onTimeout: () =>
|
|
274
|
+
new FridaDeviceAcquisitionError.FridaDeviceAcquisitionError({
|
|
275
|
+
attempts: 1,
|
|
276
|
+
acquisitionMethod: "android-emulator",
|
|
277
|
+
cause: new Error("Timeout while acquiring Android emulator device"),
|
|
278
|
+
}),
|
|
279
|
+
}),
|
|
280
|
+
Effect.catchIf(
|
|
281
|
+
Predicate.or(PlatformError.isPlatformError, ParseResult.isParseError),
|
|
282
|
+
(cause) =>
|
|
283
|
+
new FridaDeviceAcquisitionError.FridaDeviceAcquisitionError({
|
|
284
|
+
cause,
|
|
285
|
+
attempts: 1,
|
|
286
|
+
acquisitionMethod: "android-emulator",
|
|
287
|
+
})
|
|
288
|
+
)
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
/** @internal */
|
|
292
|
+
export const acquireAndroidEmulatorDeviceConfig = (
|
|
293
|
+
name: string,
|
|
294
|
+
options?:
|
|
295
|
+
| {
|
|
296
|
+
hidden?: boolean | undefined;
|
|
297
|
+
fridaExecutable?: string | undefined;
|
|
298
|
+
extraEmulatorArgs?: Array<string> | undefined;
|
|
299
|
+
}
|
|
300
|
+
| undefined
|
|
301
|
+
) =>
|
|
302
|
+
Config.string("ANDROID_SDK").pipe(
|
|
303
|
+
Config.map((androidSdk) => ({
|
|
304
|
+
adbExecutable: path.join(androidSdk, "platform-tools", "adb"),
|
|
305
|
+
emulatorExecutable: path.join(androidSdk, "emulator", "emulator"),
|
|
306
|
+
})),
|
|
307
|
+
// TODO: Should this be optional?
|
|
308
|
+
Config.withDefault({
|
|
309
|
+
adbExecutable: "adb",
|
|
310
|
+
emulatorExecutable: "emulator",
|
|
311
|
+
}),
|
|
312
|
+
Effect.flatMap((androidSdk) =>
|
|
313
|
+
acquireAndroidEmulatorDevice(name, {
|
|
314
|
+
...androidSdk,
|
|
315
|
+
...options,
|
|
316
|
+
})
|
|
317
|
+
)
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
/** @internal */
|
|
321
|
+
export const layerLocalDevice: Layer.Layer<
|
|
58
322
|
FridaDevice.FridaDevice,
|
|
59
323
|
FridaDeviceAcquisitionError.FridaDeviceAcquisitionError,
|
|
60
324
|
never
|
|
61
|
-
>
|
|
62
|
-
Effect.map(
|
|
63
|
-
Effect.tryPromise({
|
|
64
|
-
try: () => Frida.getLocalDevice(),
|
|
65
|
-
catch: (cause) =>
|
|
66
|
-
new FridaDeviceAcquisitionError.FridaDeviceAcquisitionError({
|
|
67
|
-
cause,
|
|
68
|
-
attempts: 1,
|
|
69
|
-
acquisitionMethod: "local",
|
|
70
|
-
}),
|
|
71
|
-
}),
|
|
72
|
-
(device) => ({ device, [FridaDeviceTypeId]: FridaDeviceTypeId }) as const
|
|
73
|
-
);
|
|
325
|
+
> = Layer.effect(Tag, acquireLocalDevice());
|
|
74
326
|
|
|
75
327
|
/** @internal */
|
|
76
328
|
export const layerRemoteDevice = (
|
|
77
329
|
address: string,
|
|
78
330
|
options?: Frida.RemoteDeviceOptions | undefined
|
|
79
331
|
): Layer.Layer<FridaDevice.FridaDevice, FridaDeviceAcquisitionError.FridaDeviceAcquisitionError, never> =>
|
|
80
|
-
Layer.
|
|
332
|
+
Layer.scoped(Tag, acquireRemoteDevice(address, options));
|
|
81
333
|
|
|
82
334
|
/** @internal */
|
|
83
335
|
export const layerUsbDevice = (
|
|
@@ -86,8 +338,35 @@ export const layerUsbDevice = (
|
|
|
86
338
|
Layer.effect(Tag, acquireUsbDevice(options));
|
|
87
339
|
|
|
88
340
|
/** @internal */
|
|
89
|
-
export const
|
|
341
|
+
export const layerAndroidEmulatorDevice = (
|
|
342
|
+
name: string,
|
|
343
|
+
options?:
|
|
344
|
+
| {
|
|
345
|
+
hidden?: boolean | undefined;
|
|
346
|
+
adbExecutable?: string | undefined;
|
|
347
|
+
fridaExecutable?: string | undefined;
|
|
348
|
+
emulatorExecutable?: string | undefined;
|
|
349
|
+
extraEmulatorArgs?: Array<string> | undefined;
|
|
350
|
+
}
|
|
351
|
+
| undefined
|
|
352
|
+
): Layer.Layer<
|
|
90
353
|
FridaDevice.FridaDevice,
|
|
91
354
|
FridaDeviceAcquisitionError.FridaDeviceAcquisitionError,
|
|
92
|
-
|
|
93
|
-
>
|
|
355
|
+
CommandExecutor.CommandExecutor
|
|
356
|
+
> => Layer.scoped(Tag, acquireAndroidEmulatorDevice(name, options));
|
|
357
|
+
|
|
358
|
+
/** @internal */
|
|
359
|
+
export const layerAndroidEmulatorDeviceConfig = (
|
|
360
|
+
name: string,
|
|
361
|
+
options?:
|
|
362
|
+
| {
|
|
363
|
+
hidden?: boolean | undefined;
|
|
364
|
+
fridaExecutable?: string | undefined;
|
|
365
|
+
extraEmulatorArgs?: Array<string> | undefined;
|
|
366
|
+
}
|
|
367
|
+
| undefined
|
|
368
|
+
): Layer.Layer<
|
|
369
|
+
FridaDevice.FridaDevice,
|
|
370
|
+
ConfigError.ConfigError | FridaDeviceAcquisitionError.FridaDeviceAcquisitionError,
|
|
371
|
+
CommandExecutor.CommandExecutor
|
|
372
|
+
> => Layer.scoped(Tag, acquireAndroidEmulatorDeviceConfig(name, options));
|