pymobiledevice3 5.0.1__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 +442 -421
- 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.1.dist-info → pymobiledevice3-5.0.2.dist-info}/METADATA +1 -1
- pymobiledevice3-5.0.2.dist-info/RECORD +173 -0
- pymobiledevice3-5.0.1.dist-info/RECORD +0 -173
- {pymobiledevice3-5.0.1.dist-info → pymobiledevice3-5.0.2.dist-info}/WHEEL +0 -0
- {pymobiledevice3-5.0.1.dist-info → pymobiledevice3-5.0.2.dist-info}/entry_points.txt +0 -0
- {pymobiledevice3-5.0.1.dist-info → pymobiledevice3-5.0.2.dist-info}/licenses/LICENSE +0 -0
- {pymobiledevice3-5.0.1.dist-info → pymobiledevice3-5.0.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(
|