Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
morellexf13 committed Oct 11, 2023
2 parents 11d5c72 + 22bd41f commit f916b72
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 21 deletions.
4 changes: 4 additions & 0 deletions pymobiledevice3/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,3 +290,7 @@ class CoreDeviceError(PyMobileDevice3Exception):
class AccessDeniedError(PyMobileDevice3Exception):
""" Need extra permissions to execute this command """
pass


class NoSuchBuildIdentityError(PyMobileDevice3Exception):
pass
4 changes: 4 additions & 0 deletions pymobiledevice3/remote/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ def stop_remoted_if_required() -> None:
return

remoted = get_remoted_process()
if remoted is None:
return
if remoted.status() == 'stopped':
# process already stopped, we don't need to do anything
return
Expand All @@ -43,6 +45,8 @@ def resume_remoted_if_required() -> None:
return

remoted = get_remoted_process()
if remoted is None:
return
if remoted.status() == 'running':
# process already running, we don't need to do anything
return
Expand Down
2 changes: 1 addition & 1 deletion pymobiledevice3/services/amfi.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def enable_developer_mode(self, enable_post_restart=True):
try:
self._lockdown = create_using_usbmux(self._lockdown.udid)
break
except (NoDeviceConnectedError, ConnectionFailedError, BadDevError, construct.core.StreamError):
except (NoDeviceConnectedError, ConnectionFailedError, BadDevError, OSError, construct.core.StreamError):
pass

retries = retries + 1
Expand Down
6 changes: 4 additions & 2 deletions pymobiledevice3/services/mobile_image_mounter.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

from pymobiledevice3.common import get_home_folder
from pymobiledevice3.exceptions import AlreadyMountedError, DeveloperDiskImageNotFoundError, \
DeveloperModeIsNotEnabledError, InternalError, MessageNotSupportedError, MissingManifestError, NotMountedError, \
PyMobileDevice3Exception, UnsupportedCommandError, DeviceHasPasscodeSetError
DeveloperModeIsNotEnabledError, InternalError, MessageNotSupportedError, MissingManifestError, \
NoSuchBuildIdentityError, NotMountedError, PyMobileDevice3Exception, UnsupportedCommandError
from pymobiledevice3.lockdown import LockdownClient
from pymobiledevice3.lockdown_service_provider import LockdownServiceProvider
from pymobiledevice3.restore.tss import TSSRequest
Expand Down Expand Up @@ -236,6 +236,8 @@ def get_manifest_from_tss(self, build_manifest: Mapping) -> bytes:
int(tmp_build_identity['ApChipID'], 0) == chip_id:
build_identity = tmp_build_identity
break
else:
raise NoSuchBuildIdentityError(f'Could not find the manifest for board {board_id} and chip {chip_id}')
manifest = build_identity['Manifest']

parameters = {
Expand Down
45 changes: 30 additions & 15 deletions pymobiledevice3/services/web_protocol/inspector_session.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import asyncio
import json
import logging
from typing import Mapping
from typing import Mapping, Optional

from pymobiledevice3.exceptions import InspectorEvaluateError
from pymobiledevice3.services.web_protocol.session_protocol import SessionProtocol
Expand All @@ -11,7 +11,7 @@

class InspectorSession:

def __init__(self, protocol: SessionProtocol, target_id: str):
def __init__(self, protocol: SessionProtocol, target_id: Optional[str] = None):
"""
:param pymobiledevice3.services.web_protocol.session_protocol.SessionProtocol protocol: Session protocol.
"""
Expand All @@ -30,18 +30,21 @@ def __init__(self, protocol: SessionProtocol, target_id: str):
self._receive_task = asyncio.create_task(self._receive_loop())

@classmethod
async def create(cls, protocol: SessionProtocol):
async def create(cls, protocol: SessionProtocol, wait_target: bool = True):
"""
:param pymobiledevice3.services.web_protocol.session_protocol.SessionProtocol protocol: Session protocol.
:param bool wait_target: Wait for target. If not, all operations won't have a window context to operate in
"""
await protocol.inspector.setup_inspector_socket(protocol.id_, protocol.app.id_, protocol.page.id_)
while not protocol.inspector.wir_events:
await asyncio.sleep(0)
created = protocol.inspector.wir_events.pop(0)
while 'targetInfo' not in created['params']:
target_id = None
if wait_target:
while not protocol.inspector.wir_events:
await asyncio.sleep(0)
created = protocol.inspector.wir_events.pop(0)
target_id = created['params']['targetInfo']['targetId']
logger.info(f'Created: {target_id}')
while 'targetInfo' not in created['params']:
created = protocol.inspector.wir_events.pop(0)
target_id = created['params']['targetInfo']['targetId']
logger.info(f'Created: {target_id}')
target = cls(protocol, target_id)
return target

Expand All @@ -50,7 +53,11 @@ def set_target_id(self, target_id):
logger.info(f'Changed to: {target_id}')

async def runtime_enable(self):
await self.send_and_receive({'method': 'Runtime.enable', 'params': {}})
command = {'method': 'Runtime.enable', 'params': {}}
if self.target_id is None:
await self.protocol.send_command(command)
else:
await self.send_and_receive(command)

async def runtime_evaluate(self, exp: str):
# if the expression is dict, it's needed to be in ()
Expand Down Expand Up @@ -80,8 +87,12 @@ async def navigate_to_url(self, url: str):
return await self.runtime_evaluate(exp=f'window.location = "{url}"')

async def send_and_receive(self, message: Mapping) -> Mapping:
message_id = await self.send_message_to_target(message)
return await self.receive_response_by_id(message_id)
if self.target_id is None:
message_id = await self.protocol.send_command(message['method'], **message.get('params', {}))
return await self.protocol.wait_for_message(message_id)
else:
message_id = await self.send_message_to_target(message)
return await self.receive_response_by_id(message_id)

async def send_message_to_target(self, message: Mapping) -> int:
message['id'] = self.message_id
Expand All @@ -108,9 +119,11 @@ async def receive_response_by_id(self, message_id: int) -> Mapping:
return self._dispatch_message_responses.pop(message_id)
await asyncio.sleep(0)

@staticmethod
def _parse_runtime_evaluate(response: Mapping):
message = json.loads(response['params']['message'])
def _parse_runtime_evaluate(self, response: Mapping):
if self.target_id is None:
message = response
else:
message = json.loads(response['params']['message'])
if 'error' in message:
details = message['error']['message']
logger.error(details)
Expand All @@ -121,6 +134,8 @@ def _parse_runtime_evaluate(response: Mapping):
details = result['description']
logger.error(details)
raise InspectorEvaluateError(details)
elif result['type'] == 'bigint':
return result['description']
elif result['type'] == 'undefined':
pass
else:
Expand Down
5 changes: 3 additions & 2 deletions pymobiledevice3/services/webinspector.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,10 @@ def automation_session(self, app: Application) -> AutomationSession:
self.await_(asyncio.sleep(0))
return AutomationSession(SessionProtocol(self, session_id, app, page))

async def inspector_session(self, app: Application, page: Page) -> InspectorSession:
async def inspector_session(self, app: Application, page: Page, wait_target: bool = True) -> InspectorSession:
session_id = str(uuid.uuid4()).upper()
return await InspectorSession.create(SessionProtocol(self, session_id, app, page, method_prefix=''))
return await InspectorSession.create(SessionProtocol(self, session_id, app, page, method_prefix=''),
wait_target=wait_target)

def get_open_pages(self) -> Mapping:
apps = {}
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "pymobiledevice3"
version = "2.11.0"
version = "2.12.1"
description = "Pure python3 implementation for working with iDevices (iPhone, etc...)"
readme = "README.md"
requires-python = ">=3.8"
Expand Down

0 comments on commit f916b72

Please sign in to comment.