Skip to content

Commit 1b86155

Browse files
committed
fix: optimize iframe resolution logic by adjusting backend node ID checks and enhancing child frame handling
1 parent ab0babb commit 1b86155

File tree

2 files changed

+32
-18
lines changed

2 files changed

+32
-18
lines changed

pydoll/elements/web_element.py

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -915,26 +915,29 @@ async def _resolve_oopif_by_parent(
915915
root_frame = (frame_tree or {}).get('frame', {})
916916
root_frame_id = root_frame.get('id', '')
917917

918-
is_matching_owner = False
919-
if root_frame_id and backend_node_id is not None:
920-
owner_backend_id = await self._owner_backend_for(
921-
self._connection_handler, None, root_frame_id
922-
)
923-
is_matching_owner = owner_backend_id == backend_node_id
924-
925-
if is_matching_owner or (backend_node_id is None and is_single_child and root_frame_id):
918+
if is_single_child and root_frame_id and backend_node_id is None:
926919
return (
927920
browser_handler,
928921
attached_session_id,
929922
root_frame_id,
930923
root_frame.get('url'),
931924
)
932925

926+
if root_frame_id and backend_node_id is not None:
927+
owner_backend_id = await self._owner_backend_for(
928+
self._connection_handler, None, root_frame_id
929+
)
930+
if owner_backend_id == backend_node_id:
931+
return (
932+
browser_handler,
933+
attached_session_id,
934+
root_frame_id,
935+
root_frame.get('url'),
936+
)
937+
933938
for target_info in target_infos:
934939
if target_info.get('type') not in {'iframe', 'page'}:
935940
continue
936-
if backend_node_id is None:
937-
continue
938941
attach_response = await browser_handler.execute_command(
939942
TargetCommands.attach_to_target(
940943
target_id=target_info.get('targetId', ''), flatten=True
@@ -947,7 +950,7 @@ async def _resolve_oopif_by_parent(
947950
root_frame = (frame_tree or {}).get('frame', {})
948951
root_frame_id = root_frame.get('id', '')
949952

950-
if root_frame_id:
953+
if root_frame_id and backend_node_id is not None:
951954
owner_backend_id = await self._owner_backend_for(
952955
self._connection_handler, None, root_frame_id
953956
)
@@ -959,14 +962,18 @@ async def _resolve_oopif_by_parent(
959962
root_frame.get('url'),
960963
)
961964

965+
child_frame_id = WebElement._find_child_by_parent(frame_tree, parent_frame_id)
966+
if child_frame_id:
967+
return browser_handler, attached_session_id, child_frame_id, None
968+
962969
return None, None, None, None
963970

964971
@staticmethod
965972
def _extract_frame_metadata(
966973
node_info: Node,
967974
) -> tuple[Optional[str], Optional[str], Optional[str], Optional[int]]:
968975
"""
969-
Extract iframe-related metadata from a DOM.describeNode Node.
976+
Extract iframe-related metadata from a DOM.describeNode Node.task
970977
971978
Args:
972979
node_info (Node): DOM node information of the iframe element.
@@ -1050,7 +1057,7 @@ async def _resolve_oopif_if_needed(
10501057
tuple[ConnectionHandler | None, str | None, str | None, str | None]:
10511058
(session_handler, session_id, frame_id, document_url).
10521059
"""
1053-
if not parent_frame_id:
1060+
if not parent_frame_id or (current_frame_id and backend_node_id is None):
10541061
return None, None, current_frame_id, current_document_url
10551062

10561063
(
@@ -1060,15 +1067,15 @@ async def _resolve_oopif_if_needed(
10601067
resolved_url,
10611068
) = await self._resolve_oopif_by_parent(parent_frame_id, backend_node_id)
10621069

1063-
if session_handler and session_id:
1070+
if session_handler and session_id and resolved_url:
10641071
return (
10651072
session_handler,
10661073
session_id,
10671074
resolved_frame_id or current_frame_id,
10681075
resolved_url or current_document_url,
10691076
)
10701077

1071-
return None, None, current_frame_id, current_document_url
1078+
return None, None, current_frame_id or resolved_frame_id, current_document_url or resolved_url
10721079

10731080
def _init_iframe_context(
10741081
self,

tests/test_web_element.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1904,8 +1904,10 @@ async def side_effect(command, timeout=60):
19041904
return {
19051905
'result': {
19061906
'node': {
1907+
# Simula um iframe de mesma origem já com frameId
1908+
# resolvido; não precisamos de backendNodeId aqui,
1909+
# pois não queremos acionar a resolução OOPIF.
19071910
'frameId': 'parent-frame',
1908-
'backendNodeId': 999,
19091911
'contentDocument': {
19101912
'frameId': 'iframe-123',
19111913
'documentURL': 'https://example.com/frame.html',
@@ -2435,9 +2437,14 @@ async def side_effect(command, timeout=60):
24352437
}
24362438
}
24372439
}
2440+
if method == 'DOM.getFrameOwner':
2441+
# For direct-child success, owner _does_ match backend_node_id
2442+
return {'result': {'backendNodeId': 999}}
24382443
raise AssertionError(f'Unexpected method {method}')
24392444

24402445
browser_handler.execute_command.side_effect = side_effect
2446+
# Route DOM.getFrameOwner calls from _owner_backend_for to the same side_effect
2447+
iframe_element._connection_handler.execute_command.side_effect = side_effect
24412448

24422449
handler, session_id, frame_id, url = await iframe_element._resolve_oopif_by_parent(
24432450
'parent-frame-123', 999
@@ -2687,9 +2694,9 @@ class TestResolveOOPIFIfNeeded:
26872694

26882695
@pytest.mark.asyncio
26892696
async def test_resolve_oopif_if_needed_already_has_frame_id(self, iframe_element):
2690-
"""Test OOPIF resolution skipped when frame_id already exists."""
2697+
"""Test OOPIF resolution skipped when frame_id already exists and no backend_node_id."""
26912698
handler, session_id, frame_id, url = await iframe_element._resolve_oopif_if_needed(
2692-
'existing-frame-id', 'parent-frame', 999, 'https://example.com'
2699+
'existing-frame-id', 'parent-frame', None, 'https://example.com'
26932700
)
26942701

26952702
# Should return early without resolution

0 commit comments

Comments
 (0)