pymobiledevice3 4.27.4__py3-none-any.whl → 5.1.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.
- misc/plist_sniffer.py +15 -15
- misc/remotexpc_sniffer.py +29 -28
- pymobiledevice3/__main__.py +123 -98
- pymobiledevice3/_version.py +2 -2
- pymobiledevice3/bonjour.py +351 -117
- 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 +27 -20
- 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 +601 -519
- pymobiledevice3/cli/diagnostics.py +38 -33
- pymobiledevice3/cli/lockdown.py +82 -72
- pymobiledevice3/cli/mounter.py +84 -67
- 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 +188 -111
- 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 +156 -78
- pymobiledevice3/common.py +1 -1
- pymobiledevice3/exceptions.py +154 -60
- pymobiledevice3/irecv.py +49 -53
- pymobiledevice3/irecv_devices.py +1489 -492
- pymobiledevice3/lockdown.py +400 -251
- 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 +64 -42
- pymobiledevice3/remote/tunnel_service.py +383 -297
- 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 +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 +587 -0
- pymobiledevice3/restore/recovery.py +125 -135
- pymobiledevice3/restore/restore.py +535 -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 +137 -127
- pymobiledevice3/services/afc.py +352 -292
- pymobiledevice3/services/amfi.py +21 -18
- pymobiledevice3/services/companion.py +23 -19
- pymobiledevice3/services/crash_reports.py +61 -47
- pymobiledevice3/services/debugserver_applist.py +3 -3
- pymobiledevice3/services/device_arbitration.py +8 -8
- pymobiledevice3/services/device_link.py +56 -48
- 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 +42 -52
- 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 +331 -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 +128 -74
- 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 +183 -179
- 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 +3 -3
- pymobiledevice3/services/web_protocol/session_protocol.py +15 -10
- pymobiledevice3/services/web_protocol/switch_to.py +11 -12
- pymobiledevice3/services/webinspector.py +142 -116
- pymobiledevice3/tcp_forwarder.py +35 -22
- pymobiledevice3/tunneld/api.py +20 -15
- pymobiledevice3/tunneld/server.py +310 -193
- pymobiledevice3/usbmux.py +197 -148
- pymobiledevice3/utils.py +14 -11
- {pymobiledevice3-4.27.4.dist-info → pymobiledevice3-5.1.2.dist-info}/METADATA +1 -2
- pymobiledevice3-5.1.2.dist-info/RECORD +173 -0
- pymobiledevice3-4.27.4.dist-info/RECORD +0 -172
- {pymobiledevice3-4.27.4.dist-info → pymobiledevice3-5.1.2.dist-info}/WHEEL +0 -0
- {pymobiledevice3-4.27.4.dist-info → pymobiledevice3-5.1.2.dist-info}/entry_points.txt +0 -0
- {pymobiledevice3-4.27.4.dist-info → pymobiledevice3-5.1.2.dist-info}/licenses/LICENSE +0 -0
- {pymobiledevice3-4.27.4.dist-info → pymobiledevice3-5.1.2.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
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
|
|
@@ -31,19 +32,19 @@ class ScreenCast:
|
|
|
31
32
|
|
|
32
33
|
@property
|
|
33
34
|
def scale(self) -> float:
|
|
34
|
-
"""
|
|
35
|
+
"""The amount screen pixels in one devtools pixel."""
|
|
35
36
|
real_height = self.device_height * self.page_scale_factor
|
|
36
37
|
real_width = self.device_width * self.page_scale_factor
|
|
37
38
|
return min(self.max_height / real_height, self.max_width / real_width, 1) * self.page_scale_factor
|
|
38
39
|
|
|
39
40
|
@property
|
|
40
41
|
def scaled_width(self) -> int:
|
|
41
|
-
"""
|
|
42
|
+
"""Width of screenshot after scaling."""
|
|
42
43
|
return int(self.scale * self.device_width)
|
|
43
44
|
|
|
44
45
|
@property
|
|
45
46
|
def scaled_height(self) -> int:
|
|
46
|
-
"""
|
|
47
|
+
"""Height of screenshot after scaling."""
|
|
47
48
|
return int(self.scale * self.device_height)
|
|
48
49
|
|
|
49
50
|
async def start(self, message_id: int):
|
|
@@ -53,26 +54,26 @@ class ScreenCast:
|
|
|
53
54
|
"""
|
|
54
55
|
device_size = await self.target.evaluate_and_result(
|
|
55
56
|
message_id,
|
|
56
|
-
(
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
(
|
|
58
|
+
'(window.innerWidth > 0 ? window.innerWidth : screen.width) + "," + '
|
|
59
|
+
'(window.innerHeight > 0 ? window.innerHeight : screen.height) + "," + '
|
|
60
|
+
"window.devicePixelRatio"
|
|
61
|
+
),
|
|
59
62
|
)
|
|
60
|
-
self.device_width, self.device_height, self.page_scale_factor = list(map(int, device_size.split(
|
|
63
|
+
self.device_width, self.device_height, self.page_scale_factor = list(map(int, device_size.split(",")))
|
|
61
64
|
self._run = True
|
|
62
65
|
self.recording_task = asyncio.create_task(self.recording_loop(message_id))
|
|
63
66
|
|
|
64
67
|
async def stop(self):
|
|
65
|
-
"""
|
|
68
|
+
"""Stop sending screenshots to the devtools."""
|
|
66
69
|
self._run = False
|
|
67
70
|
self.recording_task.cancel()
|
|
68
|
-
|
|
71
|
+
with contextlib.suppress(asyncio.CancelledError):
|
|
69
72
|
await self.recording_task
|
|
70
|
-
except asyncio.CancelledError:
|
|
71
|
-
pass
|
|
72
73
|
self.recording_task = None
|
|
73
74
|
|
|
74
75
|
def ack(self, frame_id: int):
|
|
75
|
-
"""
|
|
76
|
+
"""Handle acknowledgement for screencast frames."""
|
|
76
77
|
self.frames_acked.append(frame_id)
|
|
77
78
|
|
|
78
79
|
def resize_jpeg(self, data: str) -> str:
|
|
@@ -83,9 +84,9 @@ class ScreenCast:
|
|
|
83
84
|
"""
|
|
84
85
|
resized_img = Image.open(BytesIO(b64decode(data)))
|
|
85
86
|
resized_img = resized_img.resize((self.scaled_width, self.scaled_height), Image.ANTIALIAS)
|
|
86
|
-
resized_img = resized_img.convert(
|
|
87
|
+
resized_img = resized_img.convert("RGB")
|
|
87
88
|
resized = BytesIO()
|
|
88
|
-
resized_img.save(resized, format=
|
|
89
|
+
resized_img.save(resized, format="jpeg", quality="maximum")
|
|
89
90
|
return b64encode(resized.getvalue()).decode()
|
|
90
91
|
|
|
91
92
|
async def get_offsets(self, message_id: int):
|
|
@@ -96,12 +97,11 @@ class ScreenCast:
|
|
|
96
97
|
:rtype: tuple
|
|
97
98
|
"""
|
|
98
99
|
frame_size = await self.target.evaluate_and_result(
|
|
99
|
-
message_id,
|
|
100
|
-
'window.document.body.offsetTop + "," + window.pageXOffset + "," + window.pageYOffset'
|
|
100
|
+
message_id, 'window.document.body.offsetTop + "," + window.pageXOffset + "," + window.pageYOffset'
|
|
101
101
|
)
|
|
102
102
|
if frame_size is None or not isinstance(frame_size, str):
|
|
103
103
|
return 0, 0, 0
|
|
104
|
-
return tuple(map(int, frame_size.split(
|
|
104
|
+
return tuple(map(int, frame_size.split(",")))
|
|
105
105
|
|
|
106
106
|
async def recording_loop(self, message_id):
|
|
107
107
|
"""
|
|
@@ -114,24 +114,32 @@ class ScreenCast:
|
|
|
114
114
|
continue
|
|
115
115
|
self.frame_id += 1
|
|
116
116
|
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
|
-
|
|
117
|
+
event = await self.target.send_message_with_result(
|
|
118
|
+
message_id,
|
|
119
|
+
"Page.snapshotRect",
|
|
120
|
+
{
|
|
121
|
+
"x": 0,
|
|
122
|
+
"y": 0,
|
|
123
|
+
"width": self.device_width,
|
|
124
|
+
"height": self.device_height,
|
|
125
|
+
"coordinateSystem": "Viewport",
|
|
126
|
+
},
|
|
127
|
+
)
|
|
128
|
+
data = event["result"]["dataURL"]
|
|
129
|
+
data = data[data.find("base64,") + 7 :]
|
|
122
130
|
await self.target.output_queue.put({
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
}
|
|
131
|
+
"method": "Page.screencastFrame",
|
|
132
|
+
"params": {
|
|
133
|
+
"data": self.resize_jpeg(data),
|
|
134
|
+
"sessionId": self.frame_id - 1,
|
|
135
|
+
"metadata": {
|
|
136
|
+
"pageScaleFactor": self.page_scale_factor,
|
|
137
|
+
"offsetTop": offset_top,
|
|
138
|
+
"deviceWidth": self.scaled_width,
|
|
139
|
+
"deviceHeight": self.scaled_height,
|
|
140
|
+
"scrollOffsetX": scroll_offset_x,
|
|
141
|
+
"scrollOffsetY": scroll_offset_y,
|
|
142
|
+
"timestamp": datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f"),
|
|
143
|
+
},
|
|
144
|
+
},
|
|
137
145
|
})
|
|
@@ -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(
|