pymobiledevice3 5.0.0__py3-none-any.whl → 5.0.2__py3-none-any.whl
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.
Potentially problematic release.
This version of pymobiledevice3 might be problematic. Click here for more details.
- misc/plist_sniffer.py +15 -15
- misc/remotexpc_sniffer.py +29 -28
- pymobiledevice3/__main__.py +128 -102
- pymobiledevice3/_version.py +2 -2
- pymobiledevice3/bonjour.py +26 -49
- pymobiledevice3/ca.py +32 -24
- pymobiledevice3/cli/activation.py +7 -7
- pymobiledevice3/cli/afc.py +19 -19
- pymobiledevice3/cli/amfi.py +4 -4
- pymobiledevice3/cli/apps.py +51 -39
- pymobiledevice3/cli/backup.py +58 -32
- pymobiledevice3/cli/bonjour.py +25 -18
- pymobiledevice3/cli/cli_common.py +112 -81
- pymobiledevice3/cli/companion_proxy.py +4 -4
- pymobiledevice3/cli/completions.py +10 -10
- pymobiledevice3/cli/crash.py +37 -31
- pymobiledevice3/cli/developer.py +602 -520
- pymobiledevice3/cli/diagnostics.py +38 -33
- pymobiledevice3/cli/lockdown.py +79 -74
- pymobiledevice3/cli/mounter.py +85 -68
- pymobiledevice3/cli/notification.py +10 -10
- pymobiledevice3/cli/pcap.py +19 -14
- pymobiledevice3/cli/power_assertion.py +12 -10
- pymobiledevice3/cli/processes.py +10 -10
- pymobiledevice3/cli/profile.py +88 -77
- pymobiledevice3/cli/provision.py +17 -17
- pymobiledevice3/cli/remote.py +186 -110
- pymobiledevice3/cli/restore.py +43 -40
- pymobiledevice3/cli/springboard.py +30 -28
- pymobiledevice3/cli/syslog.py +85 -58
- pymobiledevice3/cli/usbmux.py +21 -20
- pymobiledevice3/cli/version.py +3 -2
- pymobiledevice3/cli/webinspector.py +157 -79
- pymobiledevice3/common.py +1 -1
- pymobiledevice3/exceptions.py +154 -60
- pymobiledevice3/irecv.py +49 -53
- pymobiledevice3/irecv_devices.py +1489 -492
- pymobiledevice3/lockdown.py +394 -241
- pymobiledevice3/lockdown_service_provider.py +5 -7
- pymobiledevice3/osu/os_utils.py +18 -9
- pymobiledevice3/osu/posix_util.py +28 -15
- pymobiledevice3/osu/win_util.py +14 -8
- pymobiledevice3/pair_records.py +19 -19
- pymobiledevice3/remote/common.py +4 -4
- pymobiledevice3/remote/core_device/app_service.py +94 -67
- pymobiledevice3/remote/core_device/core_device_service.py +17 -14
- pymobiledevice3/remote/core_device/device_info.py +5 -5
- pymobiledevice3/remote/core_device/diagnostics_service.py +10 -8
- pymobiledevice3/remote/core_device/file_service.py +47 -33
- pymobiledevice3/remote/remote_service_discovery.py +53 -35
- pymobiledevice3/remote/remotexpc.py +62 -41
- pymobiledevice3/remote/tunnel_service.py +371 -293
- pymobiledevice3/remote/utils.py +12 -11
- pymobiledevice3/remote/xpc_message.py +145 -125
- pymobiledevice3/resources/dsc_uuid_map.py +19 -19
- pymobiledevice3/resources/firmware_notifications.py +16 -16
- pymobiledevice3/restore/asr.py +27 -27
- pymobiledevice3/restore/base_restore.py +90 -47
- pymobiledevice3/restore/consts.py +87 -66
- pymobiledevice3/restore/device.py +11 -11
- pymobiledevice3/restore/fdr.py +46 -46
- pymobiledevice3/restore/ftab.py +19 -19
- pymobiledevice3/restore/img4.py +130 -133
- pymobiledevice3/restore/mbn.py +35 -54
- pymobiledevice3/restore/recovery.py +125 -135
- pymobiledevice3/restore/restore.py +524 -523
- pymobiledevice3/restore/restore_options.py +122 -115
- pymobiledevice3/restore/restored_client.py +25 -22
- pymobiledevice3/restore/tss.py +378 -270
- pymobiledevice3/service_connection.py +50 -46
- pymobiledevice3/services/accessibilityaudit.py +136 -126
- pymobiledevice3/services/afc.py +350 -291
- pymobiledevice3/services/amfi.py +21 -18
- pymobiledevice3/services/companion.py +23 -19
- pymobiledevice3/services/crash_reports.py +60 -46
- pymobiledevice3/services/debugserver_applist.py +3 -3
- pymobiledevice3/services/device_arbitration.py +8 -8
- pymobiledevice3/services/device_link.py +55 -47
- pymobiledevice3/services/diagnostics.py +971 -968
- pymobiledevice3/services/dtfetchsymbols.py +8 -8
- pymobiledevice3/services/dvt/dvt_secure_socket_proxy.py +4 -4
- pymobiledevice3/services/dvt/dvt_testmanaged_proxy.py +4 -4
- pymobiledevice3/services/dvt/instruments/activity_trace_tap.py +85 -74
- pymobiledevice3/services/dvt/instruments/application_listing.py +2 -3
- pymobiledevice3/services/dvt/instruments/condition_inducer.py +7 -6
- pymobiledevice3/services/dvt/instruments/core_profile_session_tap.py +466 -384
- pymobiledevice3/services/dvt/instruments/device_info.py +11 -11
- pymobiledevice3/services/dvt/instruments/energy_monitor.py +1 -1
- pymobiledevice3/services/dvt/instruments/graphics.py +1 -1
- pymobiledevice3/services/dvt/instruments/location_simulation.py +1 -1
- pymobiledevice3/services/dvt/instruments/location_simulation_base.py +10 -10
- pymobiledevice3/services/dvt/instruments/network_monitor.py +17 -17
- pymobiledevice3/services/dvt/instruments/notifications.py +1 -1
- pymobiledevice3/services/dvt/instruments/process_control.py +25 -10
- pymobiledevice3/services/dvt/instruments/screenshot.py +2 -2
- pymobiledevice3/services/dvt/instruments/sysmontap.py +15 -15
- pymobiledevice3/services/dvt/testmanaged/xcuitest.py +40 -50
- pymobiledevice3/services/file_relay.py +10 -10
- pymobiledevice3/services/heartbeat.py +8 -7
- pymobiledevice3/services/house_arrest.py +12 -15
- pymobiledevice3/services/installation_proxy.py +119 -100
- pymobiledevice3/services/lockdown_service.py +12 -5
- pymobiledevice3/services/misagent.py +22 -19
- pymobiledevice3/services/mobile_activation.py +84 -72
- pymobiledevice3/services/mobile_config.py +330 -301
- pymobiledevice3/services/mobile_image_mounter.py +137 -116
- pymobiledevice3/services/mobilebackup2.py +188 -150
- pymobiledevice3/services/notification_proxy.py +11 -11
- pymobiledevice3/services/os_trace.py +69 -51
- pymobiledevice3/services/pcapd.py +306 -306
- pymobiledevice3/services/power_assertion.py +10 -9
- pymobiledevice3/services/preboard.py +4 -4
- pymobiledevice3/services/remote_fetch_symbols.py +16 -14
- pymobiledevice3/services/remote_server.py +176 -146
- pymobiledevice3/services/restore_service.py +16 -16
- pymobiledevice3/services/screenshot.py +13 -10
- pymobiledevice3/services/simulate_location.py +7 -7
- pymobiledevice3/services/springboard.py +15 -15
- pymobiledevice3/services/syslog.py +5 -5
- pymobiledevice3/services/web_protocol/alert.py +3 -3
- pymobiledevice3/services/web_protocol/automation_session.py +180 -176
- pymobiledevice3/services/web_protocol/cdp_screencast.py +44 -36
- pymobiledevice3/services/web_protocol/cdp_server.py +19 -19
- pymobiledevice3/services/web_protocol/cdp_target.py +411 -373
- pymobiledevice3/services/web_protocol/driver.py +47 -45
- pymobiledevice3/services/web_protocol/element.py +74 -63
- pymobiledevice3/services/web_protocol/inspector_session.py +106 -102
- pymobiledevice3/services/web_protocol/selenium_api.py +2 -2
- pymobiledevice3/services/web_protocol/session_protocol.py +15 -10
- pymobiledevice3/services/web_protocol/switch_to.py +11 -12
- pymobiledevice3/services/webinspector.py +127 -116
- pymobiledevice3/tcp_forwarder.py +35 -22
- pymobiledevice3/tunneld/api.py +20 -15
- pymobiledevice3/tunneld/server.py +212 -133
- pymobiledevice3/usbmux.py +183 -138
- pymobiledevice3/utils.py +14 -11
- {pymobiledevice3-5.0.0.dist-info → pymobiledevice3-5.0.2.dist-info}/METADATA +1 -1
- pymobiledevice3-5.0.2.dist-info/RECORD +173 -0
- pymobiledevice3-5.0.0.dist-info/RECORD +0 -173
- {pymobiledevice3-5.0.0.dist-info → pymobiledevice3-5.0.2.dist-info}/WHEEL +0 -0
- {pymobiledevice3-5.0.0.dist-info → pymobiledevice3-5.0.2.dist-info}/entry_points.txt +0 -0
- {pymobiledevice3-5.0.0.dist-info → pymobiledevice3-5.0.2.dist-info}/licenses/LICENSE +0 -0
- {pymobiledevice3-5.0.0.dist-info → pymobiledevice3-5.0.2.dist-info}/top_level.txt +0 -0
|
@@ -24,8 +24,13 @@ from pygments.styles import get_style_by_name
|
|
|
24
24
|
|
|
25
25
|
from pymobiledevice3.cli.cli_common import Command
|
|
26
26
|
from pymobiledevice3.common import get_home_folder
|
|
27
|
-
from pymobiledevice3.exceptions import
|
|
28
|
-
|
|
27
|
+
from pymobiledevice3.exceptions import (
|
|
28
|
+
InspectorEvaluateError,
|
|
29
|
+
LaunchingApplicationError,
|
|
30
|
+
RemoteAutomationNotEnabledError,
|
|
31
|
+
WebInspectorNotEnabledError,
|
|
32
|
+
WirError,
|
|
33
|
+
)
|
|
29
34
|
from pymobiledevice3.lockdown import LockdownClient, create_using_usbmux
|
|
30
35
|
from pymobiledevice3.lockdown_service_provider import LockdownServiceProvider
|
|
31
36
|
from pymobiledevice3.osu.os_utils import get_os_utils
|
|
@@ -34,7 +39,7 @@ from pymobiledevice3.services.web_protocol.driver import By, Cookie, WebDriver
|
|
|
34
39
|
from pymobiledevice3.services.web_protocol.inspector_session import InspectorSession
|
|
35
40
|
from pymobiledevice3.services.webinspector import SAFARI, ApplicationPage, WebinspectorService
|
|
36
41
|
|
|
37
|
-
SCRIPT =
|
|
42
|
+
SCRIPT = """
|
|
38
43
|
function inspectedPage_evalResult_getCompletions(primitiveType) {{
|
|
39
44
|
var resultSet={{}};
|
|
40
45
|
var object = primitiveType;
|
|
@@ -52,15 +57,74 @@ function inspectedPage_evalResult_getCompletions(primitiveType) {{
|
|
|
52
57
|
try {{
|
|
53
58
|
inspectedPage_evalResult_getCompletions({object})
|
|
54
59
|
}} catch (e) {{}}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
JS_RESERVED_WORDS = [
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
JS_RESERVED_WORDS = [
|
|
63
|
+
"abstract",
|
|
64
|
+
"arguments",
|
|
65
|
+
"await",
|
|
66
|
+
"boolean",
|
|
67
|
+
"break",
|
|
68
|
+
"byte",
|
|
69
|
+
"case",
|
|
70
|
+
"catch",
|
|
71
|
+
"char",
|
|
72
|
+
"class",
|
|
73
|
+
"const",
|
|
74
|
+
"continue",
|
|
75
|
+
"debugger",
|
|
76
|
+
"default",
|
|
77
|
+
"delete",
|
|
78
|
+
"do",
|
|
79
|
+
"double",
|
|
80
|
+
"else",
|
|
81
|
+
"enum",
|
|
82
|
+
"eval",
|
|
83
|
+
"export",
|
|
84
|
+
"extends",
|
|
85
|
+
"false",
|
|
86
|
+
"final",
|
|
87
|
+
"finally",
|
|
88
|
+
"float",
|
|
89
|
+
"for",
|
|
90
|
+
"function",
|
|
91
|
+
"goto",
|
|
92
|
+
"if",
|
|
93
|
+
"implements",
|
|
94
|
+
"import",
|
|
95
|
+
"in",
|
|
96
|
+
"instanceof",
|
|
97
|
+
"int",
|
|
98
|
+
"interface",
|
|
99
|
+
"let",
|
|
100
|
+
"long",
|
|
101
|
+
"native",
|
|
102
|
+
"new",
|
|
103
|
+
"null",
|
|
104
|
+
"package",
|
|
105
|
+
"private",
|
|
106
|
+
"protected",
|
|
107
|
+
"public",
|
|
108
|
+
"return",
|
|
109
|
+
"short",
|
|
110
|
+
"static",
|
|
111
|
+
"super",
|
|
112
|
+
"switch",
|
|
113
|
+
"synchronized",
|
|
114
|
+
"this",
|
|
115
|
+
"throw",
|
|
116
|
+
"throws",
|
|
117
|
+
"transient",
|
|
118
|
+
"true",
|
|
119
|
+
"try",
|
|
120
|
+
"typeof",
|
|
121
|
+
"var",
|
|
122
|
+
"void",
|
|
123
|
+
"volatile",
|
|
124
|
+
"while",
|
|
125
|
+
"with",
|
|
126
|
+
"yield",
|
|
127
|
+
]
|
|
64
128
|
|
|
65
129
|
OSUTILS = get_os_utils()
|
|
66
130
|
logger = logging.getLogger(__name__)
|
|
@@ -73,7 +137,7 @@ def cli() -> None:
|
|
|
73
137
|
|
|
74
138
|
@cli.group()
|
|
75
139
|
def webinspector() -> None:
|
|
76
|
-
"""
|
|
140
|
+
"""Access webinspector services"""
|
|
77
141
|
pass
|
|
78
142
|
|
|
79
143
|
|
|
@@ -82,11 +146,11 @@ def catch_errors(func):
|
|
|
82
146
|
try:
|
|
83
147
|
return func(*args, **kwargs)
|
|
84
148
|
except LaunchingApplicationError:
|
|
85
|
-
logger.
|
|
149
|
+
logger.exception("Unable to launch application (try to unlock device)")
|
|
86
150
|
except WebInspectorNotEnabledError:
|
|
87
|
-
logger.
|
|
151
|
+
logger.exception("Web inspector is not enable")
|
|
88
152
|
except RemoteAutomationNotEnabledError:
|
|
89
|
-
logger.
|
|
153
|
+
logger.exception("Remote automation is not enable")
|
|
90
154
|
|
|
91
155
|
return update_wrapper(catch_function, func)
|
|
92
156
|
|
|
@@ -105,7 +169,7 @@ def create_webinspector_and_launch_app(lockdown: LockdownClient, timeout: float,
|
|
|
105
169
|
|
|
106
170
|
|
|
107
171
|
@webinspector.command(cls=Command)
|
|
108
|
-
@click.option(
|
|
172
|
+
@click.option("-t", "--timeout", default=3, show_default=True, type=float)
|
|
109
173
|
@catch_errors
|
|
110
174
|
def opened_tabs(service_provider: LockdownClient, timeout):
|
|
111
175
|
"""
|
|
@@ -126,8 +190,8 @@ def opened_tabs(service_provider: LockdownClient, timeout):
|
|
|
126
190
|
|
|
127
191
|
|
|
128
192
|
@webinspector.command(cls=Command)
|
|
129
|
-
@click.argument(
|
|
130
|
-
@click.option(
|
|
193
|
+
@click.argument("url")
|
|
194
|
+
@click.option("-t", "--timeout", default=3, show_default=True, type=float)
|
|
131
195
|
@catch_errors
|
|
132
196
|
def launch(service_provider: LockdownClient, url, timeout):
|
|
133
197
|
"""
|
|
@@ -146,16 +210,16 @@ def launch(service_provider: LockdownClient, url, timeout):
|
|
|
146
210
|
inspector, safari = create_webinspector_and_launch_app(service_provider, timeout, SAFARI)
|
|
147
211
|
session = inspector.automation_session(safari)
|
|
148
212
|
driver = WebDriver(session)
|
|
149
|
-
print(
|
|
213
|
+
print("Starting session")
|
|
150
214
|
driver.start_session()
|
|
151
|
-
print(
|
|
215
|
+
print("Getting URL")
|
|
152
216
|
driver.get(url)
|
|
153
217
|
OSUTILS.wait_return()
|
|
154
218
|
session.stop_session()
|
|
155
219
|
inspector.close()
|
|
156
220
|
|
|
157
221
|
|
|
158
|
-
SHELL_USAGE =
|
|
222
|
+
SHELL_USAGE = """
|
|
159
223
|
# This shell allows you to control the web with selenium like API.
|
|
160
224
|
# The first thing you should do is creating a session:
|
|
161
225
|
driver.start_session()
|
|
@@ -173,11 +237,11 @@ driver.add_cookie(
|
|
|
173
237
|
)
|
|
174
238
|
|
|
175
239
|
# See selenium api for more features.
|
|
176
|
-
|
|
240
|
+
"""
|
|
177
241
|
|
|
178
242
|
|
|
179
243
|
@webinspector.command(cls=Command)
|
|
180
|
-
@click.option(
|
|
244
|
+
@click.option("-t", "--timeout", default=3, show_default=True, type=float)
|
|
181
245
|
@catch_errors
|
|
182
246
|
def shell(service_provider: LockdownClient, timeout):
|
|
183
247
|
"""
|
|
@@ -197,25 +261,27 @@ def shell(service_provider: LockdownClient, timeout):
|
|
|
197
261
|
driver = WebDriver(session)
|
|
198
262
|
try:
|
|
199
263
|
IPython.embed(
|
|
200
|
-
header=highlight(SHELL_USAGE, lexers.PythonLexer(), formatters.Terminal256Formatter(style=
|
|
264
|
+
header=highlight(SHELL_USAGE, lexers.PythonLexer(), formatters.Terminal256Formatter(style="native")),
|
|
201
265
|
user_ns={
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
266
|
+
"driver": driver,
|
|
267
|
+
"Cookie": Cookie,
|
|
268
|
+
"By": By,
|
|
269
|
+
},
|
|
270
|
+
)
|
|
206
271
|
finally:
|
|
207
272
|
session.stop_session()
|
|
208
273
|
inspector.close()
|
|
209
274
|
|
|
210
275
|
|
|
211
276
|
@webinspector.command(cls=Command)
|
|
212
|
-
@click.option(
|
|
213
|
-
@click.option(
|
|
214
|
-
@click.option(
|
|
215
|
-
@click.argument(
|
|
277
|
+
@click.option("-t", "--timeout", default=3, show_default=True, type=float)
|
|
278
|
+
@click.option("--automation", is_flag=True, help="Use remote automation")
|
|
279
|
+
@click.option("--no-open-safari", is_flag=True, help="Avoid opening the Safari app")
|
|
280
|
+
@click.argument("url", required=False, default="")
|
|
216
281
|
@catch_errors
|
|
217
|
-
def js_shell(
|
|
218
|
-
|
|
282
|
+
def js_shell(
|
|
283
|
+
service_provider: LockdownServiceProvider, timeout: float, automation: bool, no_open_safari: bool, url: str
|
|
284
|
+
) -> None:
|
|
219
285
|
"""
|
|
220
286
|
Create a javascript shell. This interpreter runs on your local machine,
|
|
221
287
|
but evaluates each expression on the remote
|
|
@@ -234,7 +300,7 @@ def js_shell(service_provider: LockdownServiceProvider, timeout: float, automati
|
|
|
234
300
|
asyncio.run(run_js_shell(js_shell_class, service_provider, timeout, url, not no_open_safari))
|
|
235
301
|
|
|
236
302
|
|
|
237
|
-
udid =
|
|
303
|
+
udid = ""
|
|
238
304
|
|
|
239
305
|
|
|
240
306
|
def create_app():
|
|
@@ -244,8 +310,8 @@ def create_app():
|
|
|
244
310
|
|
|
245
311
|
|
|
246
312
|
@webinspector.command(cls=Command)
|
|
247
|
-
@click.option(
|
|
248
|
-
@click.option(
|
|
313
|
+
@click.option("--host", default="127.0.0.1")
|
|
314
|
+
@click.option("--port", type=click.INT, default=9222)
|
|
249
315
|
def cdp(service_provider: LockdownClient, host, port):
|
|
250
316
|
"""
|
|
251
317
|
Start a CDP server for debugging WebViews.
|
|
@@ -256,18 +322,26 @@ def cdp(service_provider: LockdownClient, host, port):
|
|
|
256
322
|
"""
|
|
257
323
|
global udid
|
|
258
324
|
udid = service_provider.udid
|
|
259
|
-
uvicorn.run(
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
325
|
+
uvicorn.run(
|
|
326
|
+
"pymobiledevice3.cli.webinspector:create_app",
|
|
327
|
+
host=host,
|
|
328
|
+
port=port,
|
|
329
|
+
factory=True,
|
|
330
|
+
ws_ping_timeout=None,
|
|
331
|
+
ws="wsproto",
|
|
332
|
+
loop="asyncio",
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def get_js_completions(jsshell: "JsShell", obj: str, prefix: str) -> list[Completion]:
|
|
264
337
|
if obj in JS_RESERVED_WORDS:
|
|
265
338
|
return []
|
|
266
339
|
|
|
267
340
|
completions = []
|
|
268
341
|
try:
|
|
269
342
|
for key in asyncio.get_running_loop().run_until_complete(
|
|
270
|
-
|
|
343
|
+
jsshell.evaluate_expression(SCRIPT.format(object=obj), return_by_value=True)
|
|
344
|
+
):
|
|
271
345
|
if not key.startswith(prefix):
|
|
272
346
|
continue
|
|
273
347
|
completions.append(Completion(key.removeprefix(prefix), display=key))
|
|
@@ -278,22 +352,20 @@ def get_js_completions(jsshell: 'JsShell', obj: str, prefix: str) -> list[Comple
|
|
|
278
352
|
|
|
279
353
|
|
|
280
354
|
class JsShellCompleter(Completer):
|
|
281
|
-
def __init__(self, jsshell:
|
|
355
|
+
def __init__(self, jsshell: "JsShell"):
|
|
282
356
|
self.jsshell = jsshell
|
|
283
357
|
|
|
284
|
-
def get_completions(
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
text = f'globalThis.{document.text_before_cursor}'
|
|
288
|
-
text = re.findall('[a-zA-Z_][a-zA-Z_0-9.]+', text)
|
|
358
|
+
def get_completions(self, document: Document, complete_event: CompleteEvent) -> Iterable[Completion]:
|
|
359
|
+
text = f"globalThis.{document.text_before_cursor}"
|
|
360
|
+
text = re.findall("[a-zA-Z_][a-zA-Z_0-9.]+", text)
|
|
289
361
|
if len(text) == 0:
|
|
290
362
|
return []
|
|
291
363
|
text = text[-1]
|
|
292
|
-
if
|
|
293
|
-
js_obj, prefix = text.rsplit(
|
|
364
|
+
if "." in text:
|
|
365
|
+
js_obj, prefix = text.rsplit(".", 1)
|
|
294
366
|
else:
|
|
295
367
|
js_obj = text
|
|
296
|
-
prefix =
|
|
368
|
+
prefix = ""
|
|
297
369
|
|
|
298
370
|
return get_js_completions(self.jsshell, js_obj, prefix)
|
|
299
371
|
|
|
@@ -301,11 +373,13 @@ class JsShellCompleter(Completer):
|
|
|
301
373
|
class JsShell(ABC):
|
|
302
374
|
def __init__(self) -> None:
|
|
303
375
|
super().__init__()
|
|
304
|
-
self.prompt_session = PromptSession(
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
376
|
+
self.prompt_session = PromptSession(
|
|
377
|
+
lexer=PygmentsLexer(lexers.JavascriptLexer),
|
|
378
|
+
auto_suggest=AutoSuggestFromHistory(),
|
|
379
|
+
style=style_from_pygments_cls(get_style_by_name("stata-dark")),
|
|
380
|
+
history=FileHistory(self.webinspector_history_path()),
|
|
381
|
+
completer=JsShellCompleter(self),
|
|
382
|
+
)
|
|
309
383
|
|
|
310
384
|
@classmethod
|
|
311
385
|
@abstractmethod
|
|
@@ -328,20 +402,19 @@ class JsShell(ABC):
|
|
|
328
402
|
return
|
|
329
403
|
|
|
330
404
|
result = await self.evaluate_expression(exp)
|
|
331
|
-
colorful_result = highlight(
|
|
332
|
-
|
|
333
|
-
|
|
405
|
+
colorful_result = highlight(
|
|
406
|
+
f"{result}", lexers.JavascriptLexer(), formatters.Terminal256Formatter(style="stata-dark")
|
|
407
|
+
)
|
|
408
|
+
print(colorful_result, end="")
|
|
334
409
|
|
|
335
|
-
async def start(self, url: str =
|
|
410
|
+
async def start(self, url: str = ""):
|
|
336
411
|
if url:
|
|
337
412
|
await self.navigate(url)
|
|
338
413
|
while True:
|
|
339
414
|
try:
|
|
340
415
|
await self.js_iter()
|
|
341
|
-
except WirError
|
|
342
|
-
logger.
|
|
343
|
-
except InspectorEvaluateError as e:
|
|
344
|
-
logger.error(e)
|
|
416
|
+
except (WirError, InspectorEvaluateError):
|
|
417
|
+
logger.exception("Failed in js_iter")
|
|
345
418
|
except KeyboardInterrupt: # KeyboardInterrupt Control-C
|
|
346
419
|
pass
|
|
347
420
|
except EOFError: # Control-D
|
|
@@ -349,7 +422,7 @@ class JsShell(ABC):
|
|
|
349
422
|
|
|
350
423
|
@staticmethod
|
|
351
424
|
def webinspector_history_path() -> str:
|
|
352
|
-
return str(get_home_folder() /
|
|
425
|
+
return str(get_home_folder() / "webinspector_history")
|
|
353
426
|
|
|
354
427
|
|
|
355
428
|
class AutomationJsShell(JsShell):
|
|
@@ -359,7 +432,7 @@ class AutomationJsShell(JsShell):
|
|
|
359
432
|
|
|
360
433
|
@classmethod
|
|
361
434
|
@asynccontextmanager
|
|
362
|
-
async def create(cls, lockdown: LockdownClient, timeout: float, open_safari: bool) ->
|
|
435
|
+
async def create(cls, lockdown: LockdownClient, timeout: float, open_safari: bool) -> "AutomationJsShell":
|
|
363
436
|
inspector, application = create_webinspector_and_launch_app(lockdown, timeout, SAFARI)
|
|
364
437
|
automation_session = inspector.automation_session(application)
|
|
365
438
|
driver = WebDriver(automation_session)
|
|
@@ -371,7 +444,7 @@ class AutomationJsShell(JsShell):
|
|
|
371
444
|
inspector.close()
|
|
372
445
|
|
|
373
446
|
async def evaluate_expression(self, exp: str, return_by_value: bool = False):
|
|
374
|
-
return self.driver.execute_script(f
|
|
447
|
+
return self.driver.execute_script(f"return {exp}")
|
|
375
448
|
|
|
376
449
|
async def navigate(self, url: str):
|
|
377
450
|
self.driver.get(url)
|
|
@@ -384,7 +457,7 @@ class InspectorJsShell(JsShell):
|
|
|
384
457
|
|
|
385
458
|
@classmethod
|
|
386
459
|
@asynccontextmanager
|
|
387
|
-
async def create(cls, lockdown: LockdownClient, timeout: float, open_safari: bool) ->
|
|
460
|
+
async def create(cls, lockdown: LockdownClient, timeout: float, open_safari: bool) -> "InspectorJsShell":
|
|
388
461
|
inspector = WebinspectorService(lockdown=lockdown)
|
|
389
462
|
inspector.connect(timeout)
|
|
390
463
|
if open_safari:
|
|
@@ -409,22 +482,27 @@ class InspectorJsShell(JsShell):
|
|
|
409
482
|
await self.inspector_session.navigate_to_url(url)
|
|
410
483
|
|
|
411
484
|
@staticmethod
|
|
412
|
-
def query_page(
|
|
413
|
-
|
|
485
|
+
def query_page(
|
|
486
|
+
inspector: WebinspectorService, bundle_identifier: Optional[str] = None
|
|
487
|
+
) -> Optional[ApplicationPage]:
|
|
414
488
|
available_pages = inspector.get_open_application_pages(timeout=1)
|
|
415
489
|
if bundle_identifier is not None:
|
|
416
|
-
available_pages = [
|
|
417
|
-
|
|
490
|
+
available_pages = [
|
|
491
|
+
application_page
|
|
492
|
+
for application_page in available_pages
|
|
493
|
+
if application_page.application.bundle == bundle_identifier
|
|
494
|
+
]
|
|
418
495
|
if not available_pages:
|
|
419
|
-
logger.error(
|
|
496
|
+
logger.error("Unable to find available pages (try to unlock device)")
|
|
420
497
|
return None
|
|
421
498
|
|
|
422
|
-
page_query = [inquirer3.List(
|
|
423
|
-
page = inquirer3.prompt(page_query, theme=GreenPassion(), raise_keyboard_interrupt=True)[
|
|
499
|
+
page_query = [inquirer3.List("page", message="choose page", choices=available_pages, carousel=True)]
|
|
500
|
+
page = inquirer3.prompt(page_query, theme=GreenPassion(), raise_keyboard_interrupt=True)["page"]
|
|
424
501
|
return page
|
|
425
502
|
|
|
426
503
|
|
|
427
|
-
async def run_js_shell(
|
|
428
|
-
|
|
504
|
+
async def run_js_shell(
|
|
505
|
+
js_shell_class: type[JsShell], lockdown: LockdownServiceProvider, timeout: float, url: str, open_safari: bool
|
|
506
|
+
) -> None:
|
|
429
507
|
async with js_shell_class.create(lockdown, timeout, open_safari) as js_shell_instance:
|
|
430
508
|
await js_shell_instance.start(url)
|
pymobiledevice3/common.py
CHANGED
|
@@ -3,7 +3,7 @@ from pathlib import Path
|
|
|
3
3
|
from pymobiledevice3.osu.os_utils import get_os_utils
|
|
4
4
|
|
|
5
5
|
_OS_UTILS = get_os_utils()
|
|
6
|
-
_HOMEFOLDER = _OS_UTILS.get_homedir() /
|
|
6
|
+
_HOMEFOLDER = _OS_UTILS.get_homedir() / ".pymobiledevice3"
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def get_home_folder() -> Path:
|