pymobiledevice3 4.14.6__py3-none-any.whl → 7.0.6__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.
- misc/plist_sniffer.py +15 -15
- misc/remotexpc_sniffer.py +29 -28
- misc/understanding_idevice_protocol_layers.md +15 -10
- pymobiledevice3/__main__.py +317 -127
- pymobiledevice3/_version.py +22 -4
- pymobiledevice3/bonjour.py +358 -113
- pymobiledevice3/ca.py +253 -16
- pymobiledevice3/cli/activation.py +31 -23
- pymobiledevice3/cli/afc.py +49 -40
- pymobiledevice3/cli/amfi.py +16 -21
- pymobiledevice3/cli/apps.py +87 -42
- pymobiledevice3/cli/backup.py +160 -90
- pymobiledevice3/cli/bonjour.py +44 -40
- pymobiledevice3/cli/cli_common.py +204 -198
- pymobiledevice3/cli/companion_proxy.py +14 -14
- pymobiledevice3/cli/crash.py +105 -56
- pymobiledevice3/cli/developer/__init__.py +62 -0
- pymobiledevice3/cli/developer/accessibility/__init__.py +65 -0
- pymobiledevice3/cli/developer/accessibility/settings.py +43 -0
- pymobiledevice3/cli/developer/arbitration.py +50 -0
- pymobiledevice3/cli/developer/condition.py +33 -0
- pymobiledevice3/cli/developer/core_device.py +294 -0
- pymobiledevice3/cli/developer/debugserver.py +244 -0
- pymobiledevice3/cli/developer/dvt/__init__.py +438 -0
- pymobiledevice3/cli/developer/dvt/core_profile_session.py +295 -0
- pymobiledevice3/cli/developer/dvt/simulate_location.py +56 -0
- pymobiledevice3/cli/developer/dvt/sysmon/__init__.py +69 -0
- pymobiledevice3/cli/developer/dvt/sysmon/process.py +188 -0
- pymobiledevice3/cli/developer/fetch_symbols.py +108 -0
- pymobiledevice3/cli/developer/simulate_location.py +51 -0
- pymobiledevice3/cli/diagnostics/__init__.py +75 -0
- pymobiledevice3/cli/diagnostics/battery.py +47 -0
- pymobiledevice3/cli/idam.py +42 -0
- pymobiledevice3/cli/lockdown.py +108 -103
- pymobiledevice3/cli/mounter.py +158 -99
- pymobiledevice3/cli/notification.py +38 -26
- pymobiledevice3/cli/pcap.py +45 -24
- pymobiledevice3/cli/power_assertion.py +18 -17
- pymobiledevice3/cli/processes.py +17 -23
- pymobiledevice3/cli/profile.py +165 -109
- pymobiledevice3/cli/provision.py +35 -34
- pymobiledevice3/cli/remote.py +217 -129
- pymobiledevice3/cli/restore.py +159 -143
- pymobiledevice3/cli/springboard.py +63 -53
- pymobiledevice3/cli/syslog.py +193 -86
- pymobiledevice3/cli/usbmux.py +73 -33
- pymobiledevice3/cli/version.py +5 -7
- pymobiledevice3/cli/webinspector.py +376 -214
- pymobiledevice3/common.py +3 -1
- pymobiledevice3/exceptions.py +182 -58
- pymobiledevice3/irecv.py +52 -53
- pymobiledevice3/irecv_devices.py +1489 -464
- pymobiledevice3/lockdown.py +473 -275
- pymobiledevice3/lockdown_service_provider.py +15 -8
- pymobiledevice3/osu/os_utils.py +27 -9
- pymobiledevice3/osu/posix_util.py +34 -15
- pymobiledevice3/osu/win_util.py +14 -8
- pymobiledevice3/pair_records.py +102 -21
- pymobiledevice3/remote/common.py +8 -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 +19 -4
- pymobiledevice3/remote/core_device/file_service.py +53 -23
- pymobiledevice3/remote/remote_service_discovery.py +79 -45
- pymobiledevice3/remote/remotexpc.py +73 -44
- pymobiledevice3/remote/tunnel_service.py +442 -317
- pymobiledevice3/remote/utils.py +14 -13
- pymobiledevice3/remote/xpc_message.py +145 -125
- pymobiledevice3/resources/dsc_uuid_map.py +19 -19
- pymobiledevice3/resources/firmware_notifications.py +20 -16
- pymobiledevice3/resources/notifications.txt +144 -0
- pymobiledevice3/restore/asr.py +27 -27
- pymobiledevice3/restore/base_restore.py +110 -21
- pymobiledevice3/restore/consts.py +87 -66
- pymobiledevice3/restore/device.py +59 -12
- pymobiledevice3/restore/fdr.py +46 -48
- pymobiledevice3/restore/ftab.py +19 -19
- pymobiledevice3/restore/img4.py +163 -0
- pymobiledevice3/restore/mbn.py +587 -0
- pymobiledevice3/restore/recovery.py +151 -151
- pymobiledevice3/restore/restore.py +562 -544
- pymobiledevice3/restore/restore_options.py +131 -110
- pymobiledevice3/restore/restored_client.py +51 -31
- pymobiledevice3/restore/tss.py +385 -267
- pymobiledevice3/service_connection.py +252 -59
- pymobiledevice3/services/accessibilityaudit.py +202 -120
- pymobiledevice3/services/afc.py +962 -365
- pymobiledevice3/services/amfi.py +24 -30
- pymobiledevice3/services/companion.py +23 -19
- pymobiledevice3/services/crash_reports.py +71 -47
- pymobiledevice3/services/debugserver_applist.py +3 -3
- pymobiledevice3/services/device_arbitration.py +8 -8
- pymobiledevice3/services/device_link.py +101 -79
- pymobiledevice3/services/diagnostics.py +973 -967
- 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 +20 -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 +35 -10
- pymobiledevice3/services/dvt/instruments/screenshot.py +2 -2
- pymobiledevice3/services/dvt/instruments/sysmontap.py +15 -15
- pymobiledevice3/services/dvt/testmanaged/xcuitest.py +42 -52
- pymobiledevice3/services/file_relay.py +10 -10
- pymobiledevice3/services/heartbeat.py +9 -8
- pymobiledevice3/services/house_arrest.py +16 -15
- pymobiledevice3/services/idam.py +20 -0
- pymobiledevice3/services/installation_proxy.py +173 -81
- pymobiledevice3/services/lockdown_service.py +20 -10
- pymobiledevice3/services/misagent.py +22 -19
- pymobiledevice3/services/mobile_activation.py +147 -64
- pymobiledevice3/services/mobile_config.py +331 -294
- pymobiledevice3/services/mobile_image_mounter.py +141 -113
- pymobiledevice3/services/mobilebackup2.py +203 -145
- pymobiledevice3/services/notification_proxy.py +11 -11
- pymobiledevice3/services/os_trace.py +134 -74
- pymobiledevice3/services/pcapd.py +314 -302
- pymobiledevice3/services/power_assertion.py +10 -9
- pymobiledevice3/services/preboard.py +4 -4
- pymobiledevice3/services/remote_fetch_symbols.py +21 -14
- pymobiledevice3/services/remote_server.py +176 -146
- pymobiledevice3/services/restore_service.py +16 -16
- pymobiledevice3/services/screenshot.py +15 -12
- 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 +11 -11
- pymobiledevice3/services/web_protocol/automation_session.py +251 -239
- pymobiledevice3/services/web_protocol/cdp_screencast.py +46 -37
- pymobiledevice3/services/web_protocol/cdp_server.py +19 -19
- pymobiledevice3/services/web_protocol/cdp_target.py +411 -373
- pymobiledevice3/services/web_protocol/driver.py +114 -111
- pymobiledevice3/services/web_protocol/element.py +124 -111
- pymobiledevice3/services/web_protocol/inspector_session.py +106 -102
- pymobiledevice3/services/web_protocol/selenium_api.py +49 -49
- pymobiledevice3/services/web_protocol/session_protocol.py +18 -12
- pymobiledevice3/services/web_protocol/switch_to.py +30 -27
- pymobiledevice3/services/webinspector.py +189 -155
- pymobiledevice3/tcp_forwarder.py +87 -69
- pymobiledevice3/tunneld/__init__.py +0 -0
- pymobiledevice3/tunneld/api.py +63 -0
- pymobiledevice3/tunneld/server.py +603 -0
- pymobiledevice3/usbmux.py +198 -147
- pymobiledevice3/utils.py +14 -11
- {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/METADATA +55 -28
- pymobiledevice3-7.0.6.dist-info/RECORD +188 -0
- {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/WHEEL +1 -1
- pymobiledevice3/cli/developer.py +0 -1215
- pymobiledevice3/cli/diagnostics.py +0 -99
- pymobiledevice3/tunneld.py +0 -524
- pymobiledevice3-4.14.6.dist-info/RECORD +0 -168
- {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/entry_points.txt +0 -0
- {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info/licenses}/LICENSE +0 -0
- {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/top_level.txt +0 -0
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import contextlib
|
|
2
3
|
from base64 import b64decode, b64encode
|
|
3
4
|
from datetime import datetime
|
|
4
5
|
from io import BytesIO
|
|
6
|
+
from typing import Optional
|
|
5
7
|
|
|
6
8
|
from PIL import Image
|
|
7
9
|
|
|
@@ -27,23 +29,23 @@ class ScreenCast:
|
|
|
27
29
|
self.device_height = 0
|
|
28
30
|
self.page_scale_factor = 0
|
|
29
31
|
self._run = True
|
|
30
|
-
self.recording_task
|
|
32
|
+
self.recording_task: Optional[asyncio.Task] = None
|
|
31
33
|
|
|
32
34
|
@property
|
|
33
35
|
def scale(self) -> float:
|
|
34
|
-
"""
|
|
36
|
+
"""The amount screen pixels in one devtools pixel."""
|
|
35
37
|
real_height = self.device_height * self.page_scale_factor
|
|
36
38
|
real_width = self.device_width * self.page_scale_factor
|
|
37
39
|
return min(self.max_height / real_height, self.max_width / real_width, 1) * self.page_scale_factor
|
|
38
40
|
|
|
39
41
|
@property
|
|
40
42
|
def scaled_width(self) -> int:
|
|
41
|
-
"""
|
|
43
|
+
"""Width of screenshot after scaling."""
|
|
42
44
|
return int(self.scale * self.device_width)
|
|
43
45
|
|
|
44
46
|
@property
|
|
45
47
|
def scaled_height(self) -> int:
|
|
46
|
-
"""
|
|
48
|
+
"""Height of screenshot after scaling."""
|
|
47
49
|
return int(self.scale * self.device_height)
|
|
48
50
|
|
|
49
51
|
async def start(self, message_id: int):
|
|
@@ -53,26 +55,26 @@ class ScreenCast:
|
|
|
53
55
|
"""
|
|
54
56
|
device_size = await self.target.evaluate_and_result(
|
|
55
57
|
message_id,
|
|
56
|
-
(
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
(
|
|
59
|
+
'(window.innerWidth > 0 ? window.innerWidth : screen.width) + "," + '
|
|
60
|
+
'(window.innerHeight > 0 ? window.innerHeight : screen.height) + "," + '
|
|
61
|
+
"window.devicePixelRatio"
|
|
62
|
+
),
|
|
59
63
|
)
|
|
60
|
-
self.device_width, self.device_height, self.page_scale_factor = list(map(int, device_size.split(
|
|
64
|
+
self.device_width, self.device_height, self.page_scale_factor = list(map(int, device_size.split(",")))
|
|
61
65
|
self._run = True
|
|
62
66
|
self.recording_task = asyncio.create_task(self.recording_loop(message_id))
|
|
63
67
|
|
|
64
68
|
async def stop(self):
|
|
65
|
-
"""
|
|
69
|
+
"""Stop sending screenshots to the devtools."""
|
|
66
70
|
self._run = False
|
|
67
71
|
self.recording_task.cancel()
|
|
68
|
-
|
|
72
|
+
with contextlib.suppress(asyncio.CancelledError):
|
|
69
73
|
await self.recording_task
|
|
70
|
-
except asyncio.CancelledError:
|
|
71
|
-
pass
|
|
72
74
|
self.recording_task = None
|
|
73
75
|
|
|
74
76
|
def ack(self, frame_id: int):
|
|
75
|
-
"""
|
|
77
|
+
"""Handle acknowledgement for screencast frames."""
|
|
76
78
|
self.frames_acked.append(frame_id)
|
|
77
79
|
|
|
78
80
|
def resize_jpeg(self, data: str) -> str:
|
|
@@ -83,9 +85,9 @@ class ScreenCast:
|
|
|
83
85
|
"""
|
|
84
86
|
resized_img = Image.open(BytesIO(b64decode(data)))
|
|
85
87
|
resized_img = resized_img.resize((self.scaled_width, self.scaled_height), Image.ANTIALIAS)
|
|
86
|
-
resized_img = resized_img.convert(
|
|
88
|
+
resized_img = resized_img.convert("RGB")
|
|
87
89
|
resized = BytesIO()
|
|
88
|
-
resized_img.save(resized, format=
|
|
90
|
+
resized_img.save(resized, format="jpeg", quality="maximum")
|
|
89
91
|
return b64encode(resized.getvalue()).decode()
|
|
90
92
|
|
|
91
93
|
async def get_offsets(self, message_id: int):
|
|
@@ -96,12 +98,11 @@ class ScreenCast:
|
|
|
96
98
|
:rtype: tuple
|
|
97
99
|
"""
|
|
98
100
|
frame_size = await self.target.evaluate_and_result(
|
|
99
|
-
message_id,
|
|
100
|
-
'window.document.body.offsetTop + "," + window.pageXOffset + "," + window.pageYOffset'
|
|
101
|
+
message_id, 'window.document.body.offsetTop + "," + window.pageXOffset + "," + window.pageYOffset'
|
|
101
102
|
)
|
|
102
103
|
if frame_size is None or not isinstance(frame_size, str):
|
|
103
104
|
return 0, 0, 0
|
|
104
|
-
return tuple(map(int, frame_size.split(
|
|
105
|
+
return tuple(map(int, frame_size.split(",")))
|
|
105
106
|
|
|
106
107
|
async def recording_loop(self, message_id):
|
|
107
108
|
"""
|
|
@@ -114,24 +115,32 @@ class ScreenCast:
|
|
|
114
115
|
continue
|
|
115
116
|
self.frame_id += 1
|
|
116
117
|
offset_top, scroll_offset_x, scroll_offset_y = await self.get_offsets(message_id)
|
|
117
|
-
event = await self.target.send_message_with_result(
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
118
|
+
event = await self.target.send_message_with_result(
|
|
119
|
+
message_id,
|
|
120
|
+
"Page.snapshotRect",
|
|
121
|
+
{
|
|
122
|
+
"x": 0,
|
|
123
|
+
"y": 0,
|
|
124
|
+
"width": self.device_width,
|
|
125
|
+
"height": self.device_height,
|
|
126
|
+
"coordinateSystem": "Viewport",
|
|
127
|
+
},
|
|
128
|
+
)
|
|
129
|
+
data = event["result"]["dataURL"]
|
|
130
|
+
data = data[data.find("base64,") + 7 :]
|
|
122
131
|
await self.target.output_queue.put({
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
}
|
|
132
|
+
"method": "Page.screencastFrame",
|
|
133
|
+
"params": {
|
|
134
|
+
"data": self.resize_jpeg(data),
|
|
135
|
+
"sessionId": self.frame_id - 1,
|
|
136
|
+
"metadata": {
|
|
137
|
+
"pageScaleFactor": self.page_scale_factor,
|
|
138
|
+
"offsetTop": offset_top,
|
|
139
|
+
"deviceWidth": self.scaled_width,
|
|
140
|
+
"deviceHeight": self.scaled_height,
|
|
141
|
+
"scrollOffsetX": scroll_offset_x,
|
|
142
|
+
"scrollOffsetY": scroll_offset_y,
|
|
143
|
+
"timestamp": datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f"),
|
|
144
|
+
},
|
|
145
|
+
},
|
|
137
146
|
})
|
|
@@ -19,7 +19,7 @@ async def lifespan(app: FastAPI):
|
|
|
19
19
|
app = FastAPI(lifespan=lifespan)
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
@app.get(
|
|
22
|
+
@app.get("/json{_:path}")
|
|
23
23
|
async def available_targets(_: str):
|
|
24
24
|
app.state.inspector.get_open_pages()
|
|
25
25
|
targets = []
|
|
@@ -28,47 +28,47 @@ async def available_targets(_: str):
|
|
|
28
28
|
if page.type_ not in (WirTypes.WEB, WirTypes.WEB_PAGE):
|
|
29
29
|
continue
|
|
30
30
|
targets.append({
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
"description": "",
|
|
32
|
+
"id": page_id,
|
|
33
|
+
"title": page.web_title,
|
|
34
|
+
"type": "page",
|
|
35
|
+
"url": page.web_url,
|
|
36
|
+
"webSocketDebuggerUrl": f"ws://localhost:9222/devtools/page/{page_id}",
|
|
37
|
+
"devtoolsFrontendUrl": f"/devtools/inspector.html?ws://localhost:9222/devtools/page/{page_id}",
|
|
38
38
|
})
|
|
39
39
|
return targets
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
@app.get(
|
|
42
|
+
@app.get("/json/version")
|
|
43
43
|
def version():
|
|
44
44
|
return {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
"Browser": "Safari",
|
|
46
|
+
"Protocol-Version": "1.1",
|
|
47
|
+
"User-Agent": "pymobiledevice3",
|
|
48
|
+
"V8-Version": "7.2.233",
|
|
49
|
+
"WebKit-Version": "537.36 (@cfede9db1d154de0468cb0538479f34c0755a0f4)",
|
|
50
|
+
"webSocketDebuggerUrl": f"ws://localhost:9222/devtools/browser/{app.state.inspector.connection_id}",
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
async def from_cdp(target: CdpTarget, websocket):
|
|
55
55
|
async for message in websocket.iter_json():
|
|
56
|
-
logger.debug(f
|
|
56
|
+
logger.debug(f"CDP INPUT: {message}")
|
|
57
57
|
await target.send(message)
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
async def to_cdp(target: CdpTarget, websocket):
|
|
61
61
|
while True:
|
|
62
62
|
message = await target.receive()
|
|
63
|
-
logger.debug(f
|
|
63
|
+
logger.debug(f"CDP OUTPUT: {message}")
|
|
64
64
|
await websocket.send_json(message)
|
|
65
65
|
|
|
66
66
|
|
|
67
|
-
@app.websocket(
|
|
67
|
+
@app.websocket("/devtools/page/{page_id}")
|
|
68
68
|
async def page_debugger(websocket: WebSocket, page_id: str):
|
|
69
69
|
application, page = app.state.inspector.find_page_id(page_id)
|
|
70
70
|
session_id = str(uuid.uuid4()).upper()
|
|
71
|
-
protocol = SessionProtocol(app.state.inspector, session_id, application, page, method_prefix=
|
|
71
|
+
protocol = SessionProtocol(app.state.inspector, session_id, application, page, method_prefix="")
|
|
72
72
|
target = await CdpTarget.create(protocol)
|
|
73
73
|
await websocket.accept()
|
|
74
74
|
await asyncio.gather(
|