diff --git a/moli-core/src/page/mod.rs b/moli-core/src/page/mod.rs index f4e2608a9c..16c758ab94 100644 --- a/moli-core/src/page/mod.rs +++ b/moli-core/src/page/mod.rs @@ -83,8 +83,9 @@ pub use moli_renderer_v8::network::{ }; pub use moli_renderer_v8::{ CompletedWorkerRuntimeInspectorCommandDispatch, DevToolsSessionKey, - RendererActivityDiagnostics, RendererAgentAttachmentId, RendererAutofillAddressField, - RendererAutofillCreditCard, RendererAutofillTriggerOutcome, RendererAutofillTriggerRequest, + PendingWorkerRuntimeInspectorSessionResponse, RendererActivityDiagnostics, + RendererAgentAttachmentId, RendererAutofillAddressField, RendererAutofillCreditCard, + RendererAutofillTriggerOutcome, RendererAutofillTriggerRequest, RendererCaptureScreencastFrameReply, RendererCaptureScreencastFrameRequest, RendererCaptureScreenshotReply, RendererCaptureScreenshotRequest, RendererCommandTurnCompletion, RendererCommandTurnOutput, RendererDedicatedWorkerTargetEvent, diff --git a/moli-protocol/src/conn.rs b/moli-protocol/src/conn.rs index a137f2daf9..6e708a9d34 100644 --- a/moli-protocol/src/conn.rs +++ b/moli-protocol/src/conn.rs @@ -816,8 +816,7 @@ impl DeferredMainDocumentLoadPredecessorCandidate { #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) struct RuntimeAwaitJob { command_id: u64, - session_id: Option, - owner_route: Option, + owner: CommandOwnerScope, object_group: Option, action: &'static str, } @@ -825,15 +824,13 @@ pub(crate) struct RuntimeAwaitJob { impl RuntimeAwaitJob { pub(crate) fn new( command_id: u64, - session_id: Option<&str>, - owner_route: Option, + owner: &CommandOwnerScope, object_group: Option<&str>, action: &'static str, ) -> Self { Self { command_id, - session_id: session_id.map(str::to_owned), - owner_route, + owner: owner.clone(), object_group: object_group.map(str::to_owned), action, } @@ -842,15 +839,15 @@ impl RuntimeAwaitJob { pub(crate) fn trace_fields(&self) -> serde_json::Value { json!({ "commandId": self.command_id, - "sessionId": self.session_id, - "ownerRoute": self.owner_route.as_ref().map(|route| format!("{route:?}")), + "sessionId": self.owner.session_id(), + "ownerRoute": self.owner.explicit_route().map(|route| format!("{route:?}")), "objectGroup": self.object_group, "action": self.action, }) } pub(crate) fn session_id(&self) -> Option { - self.session_id.clone() + self.owner.session_id().map(str::to_owned) } } @@ -1643,7 +1640,12 @@ impl CdpConnection { } fn target_id_for_session_owner(&self, session_id: Option<&str>) -> Option { - let (browser_context_id, target_id) = self.target_owner_identity_for_session(session_id)?; + let owner = CommandOwnerScope::capture(self, session_id); + self.target_id_for_owner(&owner) + } + + fn target_id_for_owner(&self, owner: &CommandOwnerScope) -> Option { + let (browser_context_id, target_id) = self.target_owner_identity_for_owner(owner)?; target_id.or_else(|| { self.browser_context_by_id(&browser_context_id) .and_then(BrowserContext::active_target_id) @@ -1651,11 +1653,11 @@ impl CdpConnection { }) } - pub(crate) fn session_owner_target_has_waiting_for_debugger_session( + pub(crate) fn owner_target_has_waiting_for_debugger_session( &self, - session_id: Option<&str>, + owner: &CommandOwnerScope, ) -> bool { - self.target_id_for_session_owner(session_id) + self.target_id_for_owner(owner) .is_some_and(|target_id| self.target_has_waiting_for_debugger_session(&target_id)) } @@ -1694,16 +1696,15 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> bool { - self.has_pending_document_navigation_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.has_pending_document_navigation_for_owner(&owner) } - pub(crate) fn has_pending_document_navigation_for_route( + pub(crate) fn has_pending_document_navigation_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> bool { - let Some((browser_context_id, target_id)) = - self.target_owner_identity_for_route(session_id, owner_route) + let Some((browser_context_id, target_id)) = self.target_owner_identity_for_owner(owner) else { return false; }; @@ -1713,13 +1714,11 @@ impl CdpConnection { }) } - fn document_navigation_state_for_route( + fn document_navigation_state_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> DevToolsDocumentNavigationState { - let Some((browser_context_id, target_id)) = - self.target_owner_identity_for_route(session_id, owner_route) + let Some((browser_context_id, target_id)) = self.target_owner_identity_for_owner(owner) else { return DevToolsDocumentNavigationState::Unavailable; }; @@ -1738,7 +1737,7 @@ impl CdpConnection { // Otherwise a materialized `about:blank` is misclassified as // `AwaitingCommit`, and ChromeDriver-style pre-command navigation // waits can never complete. - match self.target_session_owner_frame_tree_loader_id_for_route(session_id, owner_route) { + match self.target_session_owner_frame_tree_loader_id_for_owner(owner) { Some(loader_id) => DevToolsDocumentNavigationState::Committed { loader_id }, None => DevToolsDocumentNavigationState::AwaitingCommit, } @@ -1755,10 +1754,7 @@ impl CdpConnection { let Some(owner_scope) = self.command_owner_scope_for_devtools_context(context) else { return DevToolsDocumentNavigationState::Unavailable; }; - self.document_navigation_state_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) + self.document_navigation_state_for_owner(&owner_scope) } pub fn renderer_document_navigation_is_suspended_for_session_owner( @@ -1769,14 +1765,12 @@ impl CdpConnection { .is_ok_and(TargetRuntimeSlot::renderer_document_navigation_is_suspended) } - pub(crate) fn accepts_pending_document_navigation_for_route( + pub(crate) fn accepts_pending_document_navigation_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, token: &DocumentNavigationToken, ) -> bool { - let Some((browser_context_id, target_id)) = - self.target_owner_identity_for_route(session_id, owner_route) + let Some((browser_context_id, target_id)) = self.target_owner_identity_for_owner(owner) else { return false; }; @@ -1793,15 +1787,15 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> Result<(), String> { - self.ensure_document_accessible_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.ensure_document_accessible_for_owner(&owner) } - pub(crate) fn ensure_document_accessible_for_route( + pub(crate) fn ensure_document_accessible_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Result<(), String> { - if self.has_pending_document_navigation_for_route(session_id, owner_route) { + if self.has_pending_document_navigation_for_owner(owner) { return Err("Navigation is changing the document".to_owned()); } Ok(()) @@ -1811,15 +1805,15 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> Option { - self.current_document_loader_id_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.current_document_loader_id_for_owner(&owner) } - pub(crate) fn current_document_loader_id_for_route( + pub(crate) fn current_document_loader_id_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - self.runtime_session_owner_slot_for_route(session_id, owner_route) + self.runtime_session_owner_slot_for_owner(owner) .ok() .and_then(|slot| slot.current_document_loader_id().map(str::to_owned)) } @@ -1831,35 +1825,33 @@ impl CdpConnection { source_document: moli_core::RendererDocumentLifecycleIdentity, item: &moli_core::page::ScriptNetworkOutputItem, ) -> Option { - self.ingest_renderer_page_network_output_item_and_prepare_live_delivery_for_route( - session_id, - None, + let owner = CommandOwnerScope::capture(self, session_id); + self.ingest_renderer_page_network_output_item_and_prepare_live_delivery_for_owner( + &owner, None, source_document, item, ) } - pub(crate) fn ingest_renderer_page_network_output_item_and_prepare_live_delivery_for_route( + pub(crate) fn ingest_renderer_page_network_output_item_and_prepare_live_delivery_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, source_renderer_page: Option, source_document: moli_core::RendererDocumentLifecycleIdentity, item: &moli_core::page::ScriptNetworkOutputItem, ) -> Option { - let primary_session_id = - self.runtime_session_owner_primary_session_id_for_route(session_id, owner_route); + let primary_session_id = self.runtime_session_owner_primary_session_id_for_owner(owner); let mut request_id_allocator = std::mem::take(&mut self.network_request_id_allocator); let delivery = self - .runtime_session_owner_slot_mut_for_route(session_id, owner_route) + .runtime_session_owner_slot_mut_for_owner(owner) .ok() .and_then(|slot| { slot.ingest_renderer_network_output_item_and_prepare_live_delivery( source_renderer_page, source_document, item, - session_id, + owner.session_id(), primary_session_id.as_deref(), None, &mut request_id_allocator, @@ -1873,16 +1865,16 @@ impl CdpConnection { &mut self, session_id: Option<&str>, ) -> Result<&mut Page, String> { - self.loaded_page_mut_for_protocol_access_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.loaded_page_mut_for_protocol_access_for_owner(&owner) } - pub(crate) fn loaded_page_mut_for_protocol_access_for_route( + pub(crate) fn loaded_page_mut_for_protocol_access_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Result<&mut Page, String> { - self.ensure_document_accessible_for_route(session_id, owner_route)?; - self.loaded_page_mut_for_interruptible_protocol_access_for_route(session_id, owner_route) + self.ensure_document_accessible_for_owner(owner)?; + self.loaded_page_mut_for_interruptible_protocol_access_for_owner(owner) } /// Returns the Page that currently carries target-scoped configuration. @@ -1899,15 +1891,15 @@ impl CdpConnection { &mut self, session_id: Option<&str>, ) -> Result<&mut Page, String> { - self.loaded_page_mut_for_target_configuration_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.loaded_page_mut_for_target_configuration_for_owner(&owner) } - pub(crate) fn loaded_page_mut_for_target_configuration_for_route( + pub(crate) fn loaded_page_mut_for_target_configuration_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Result<&mut Page, String> { - self.runtime_session_owner_slot_mut_for_route(session_id, owner_route)? + self.runtime_session_owner_slot_mut_for_owner(owner)? .loaded_page_mut() .ok_or_else(|| "NoDocumentLoaded".to_owned()) } @@ -1923,27 +1915,25 @@ impl CdpConnection { &mut self, session_id: Option<&str>, ) -> Result<&mut Page, String> { - self.loaded_page_mut_for_interruptible_protocol_access_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.loaded_page_mut_for_interruptible_protocol_access_for_owner(&owner) } - pub(crate) fn loaded_page_mut_for_interruptible_protocol_access_for_route( + pub(crate) fn loaded_page_mut_for_interruptible_protocol_access_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Result<&mut Page, String> { - self.runtime_session_owner_slot_mut_for_route(session_id, owner_route)? + self.runtime_session_owner_slot_mut_for_owner(owner)? .loaded_page_mut() .ok_or_else(|| "NoDocumentLoaded".to_owned()) } - pub(crate) fn start_document_navigation_for_route( + pub(crate) fn start_document_navigation_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, loader_id: String, ) -> Option { - let (browser_context_id, target_id) = - self.target_owner_identity_for_route(session_id, owner_route)?; + let (browser_context_id, target_id) = self.target_owner_identity_for_owner(owner)?; let target_id = target_id?; self.browser_context_by_id_mut(&browser_context_id)? .start_document_navigation_for_target(&target_id, loader_id) @@ -1954,8 +1944,7 @@ impl CdpConnection { owner: &CommandOwnerScope, token: &DocumentNavigationToken, ) { - let Some((browser_context_id, target_id)) = - self.target_owner_identity_for_route(owner.session_id(), owner.session_owner_route()) + let Some((browser_context_id, target_id)) = self.target_owner_identity_for_owner(owner) else { return; }; @@ -1979,10 +1968,7 @@ impl CdpConnection { Vec, ) { let (binding, events, document_scope_changed) = { - let Ok(slot) = self.runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - ) else { + let Ok(slot) = self.runtime_session_owner_slot_mut_for_owner(owner) else { return (None, Vec::new()); }; let previous_document_scope = slot @@ -2020,10 +2006,7 @@ impl CdpConnection { Vec, ) { let (binding, events, document_scope_changed, document_input_stream_opened) = { - let Ok(slot) = self.runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - ) else { + let Ok(slot) = self.runtime_session_owner_slot_mut_for_owner(owner) else { return (None, Vec::new()); }; let previous_document_scope = slot @@ -2059,34 +2042,26 @@ impl CdpConnection { // not defer this state transition to a later diagnostics snapshot: // that would make a later owner turn rediscover and settle output // produced by this renderer turn. - self.with_target_owner_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |owner_state| owner_state.mark_initial_empty_document_exited(), - ); + self.with_target_owner_state_for_owner_mut(owner, |owner_state| { + owner_state.mark_initial_empty_document_exited() + }); } (binding, events) } fn retire_javascript_dialogs_for_owner(&mut self, owner: &CommandOwnerScope) { - let event_session_ids = - self.page_event_session_ids_for_route(owner.session_id(), owner.session_owner_route()); - if let Ok(slot) = self.runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - ) { + let event_session_ids = self.page_event_session_ids_for_owner(owner); + if let Ok(slot) = self.runtime_session_owner_slot_mut_for_owner(owner) { slot.retire_javascript_dialog_scope(); } for event_session_id in event_session_ids { - let event_owner_route = event_session_id - .is_none() - .then_some(owner.session_owner_route()) - .flatten(); - let _ = self.with_target_devtools_session_state_for_route_mut( - event_session_id.as_deref(), - event_owner_route, - |state| state.page_session_state.javascript_dialog_state.clear(), - ); + let event_owner = event_session_id + .as_deref() + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); + let _ = self.with_target_devtools_session_state_for_owner_mut(&event_owner, |state| { + state.page_session_state.javascript_dialog_state.clear() + }); } } @@ -2095,14 +2070,11 @@ impl CdpConnection { owner: &CommandOwnerScope, loader_id: &str, ) -> bool { - self.runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - ) - .is_ok_and(|slot| { - slot.page_slot_mut() - .begin_renderer_document_load_visibility_barrier(loader_id) - }) + self.runtime_session_owner_slot_mut_for_owner(owner) + .is_ok_and(|slot| { + slot.page_slot_mut() + .begin_renderer_document_load_visibility_barrier(loader_id) + }) } pub(crate) fn release_renderer_document_load_visibility_barrier_for_owner( @@ -2110,13 +2082,10 @@ impl CdpConnection { owner: &CommandOwnerScope, loader_id: &str, ) -> Option> { - self.runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - ) - .ok()? - .page_slot_mut() - .release_renderer_document_load_visibility_barrier(loader_id) + self.runtime_session_owner_slot_mut_for_owner(owner) + .ok()? + .page_slot_mut() + .release_renderer_document_load_visibility_barrier(loader_id) } pub(crate) fn cancel_renderer_document_load_visibility_barrier_for_owner( @@ -2124,14 +2093,11 @@ impl CdpConnection { owner: &CommandOwnerScope, loader_id: &str, ) -> bool { - self.runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - ) - .is_ok_and(|slot| { - slot.page_slot_mut() - .cancel_renderer_document_load_visibility_barrier(loader_id) - }) + self.runtime_session_owner_slot_mut_for_owner(owner) + .is_ok_and(|slot| { + slot.page_slot_mut() + .cancel_renderer_document_load_visibility_barrier(loader_id) + }) } #[cfg(test)] @@ -2163,10 +2129,7 @@ impl CdpConnection { RendererDocumentLifecycleObservation::Unavailable, ); }; - let Ok(slot) = self.runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - ) else { + let Ok(slot) = self.runtime_session_owner_slot_mut_for_owner(owner) else { return RendererDocumentLifecycleObserver::resolved( RendererDocumentLifecycleObservation::Unavailable, ); @@ -2197,14 +2160,11 @@ impl CdpConnection { owner: &CommandOwnerScope, loader_id: &str, ) -> bool { - self.runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - ) - .is_ok_and(|slot| { - slot.page_slot_mut() - .arm_root_post_load_observation(loader_id) - }) + self.runtime_session_owner_slot_mut_for_owner(owner) + .is_ok_and(|slot| { + slot.page_slot_mut() + .arm_root_post_load_observation(loader_id) + }) } /// Consumes the exact stopped-loading fact owned by an armed root post-load @@ -2227,10 +2187,7 @@ impl CdpConnection { }; let binding = self - .runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + .runtime_session_owner_slot_mut_for_owner(owner) .ok() .and_then(|slot| { slot.page_slot_mut() @@ -2240,19 +2197,13 @@ impl CdpConnection { return Err(SettlementError::MissingArmedObservation); }; if self - .subscribed_page_event_session_ids_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + .subscribed_page_event_session_ids_for_owner(owner) .is_empty() { return Ok(Settlement::Unobserved); } let attachments = self - .page_event_protocol_attachments_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + .page_event_protocol_attachments_for_owner(owner) .ok_or(SettlementError::SubscribedAttachmentUnavailable)?; let publish_sequence = self .scheduler_state @@ -2277,31 +2228,26 @@ impl CdpConnection { out: &mut Vec, ) -> bool { if !self - .runtime_session_owner_slot_for_route(owner.session_id(), owner.session_owner_route()) + .runtime_session_owner_slot_for_owner(owner) .is_ok_and(|slot| slot.renderer_subresources_are_idle()) { return false; } let binding = self - .runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + .runtime_session_owner_slot_mut_for_owner(owner) .ok() .and_then(|slot| slot.page_slot_mut().take_root_network_idle_binding()); let Some(binding) = binding else { return false; }; let timestamp = monotonic_timestamp_seconds(); - for event_session_id in - self.page_event_session_ids_for_route(owner.session_id(), owner.session_owner_route()) - { - let event_owner_route = event_session_id - .is_none() - .then_some(owner.session_owner_route()) - .flatten(); + for event_session_id in self.page_event_session_ids_for_owner(owner) { + let event_owner = event_session_id + .as_deref() + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); let lifecycle_enabled = self - .target_page_session_state_for_route(event_session_id.as_deref(), event_owner_route) + .target_page_session_state_for_owner(&event_owner) .is_some_and(|state| state.page_lifecycle_events); crate::domains::page::emit_navigation_network_idle_background_events( out, @@ -2333,6 +2279,14 @@ impl CdpConnection { let route = self .target_session_route_for_target_id(target_id.as_str()) .or_else(|| self.target_session_route_for_child_frame_id(target_id.as_str()))?; + if let Some(session_id) = context.session_id.as_ref() + && let Some(session_route) = self.session_route(Some(session_id.as_str())) + { + if !session_route.addresses_same_target_as(&route) { + return None; + } + return Some(CommandOwnerScope::for_session(session_id.as_str())); + } return Some(CommandOwnerScope::for_route(route)); } Some(CommandOwnerScope::capture( @@ -2352,10 +2306,7 @@ impl CdpConnection { context: &DevToolsCommandContext, ) -> Option { let owner_scope = self.command_owner_scope_for_devtools_context(context)?; - self.target_page_residence_identity_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) + self.target_page_residence_identity_for_owner(&owner_scope) } pub fn capture_devtools_document_lifecycle_wait_key( @@ -2366,10 +2317,7 @@ impl CdpConnection { ) -> Option { let owner_scope = self.command_owner_scope_for_devtools_context(context)?; let registration = self - .runtime_session_owner_slot_mut_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) + .runtime_session_owner_slot_mut_for_owner(&owner_scope) .ok()? .page_slot_mut() .register_renderer_document_lifecycle_waiter(milestone, expected_loader_id); @@ -2392,14 +2340,11 @@ impl CdpConnection { let Some(owner_scope) = self.command_owner_scope_for_devtools_context(context) else { return DevToolsDocumentLifecycleWaitState::Unavailable; }; - self.runtime_session_owner_slot_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) - .ok() - .map_or(DevToolsDocumentLifecycleWaitState::Unavailable, |slot| { - devtools_document_lifecycle_wait_state_for_slot(slot, key) - }) + self.runtime_session_owner_slot_for_owner(&owner_scope) + .ok() + .map_or(DevToolsDocumentLifecycleWaitState::Unavailable, |slot| { + devtools_document_lifecycle_wait_state_for_slot(slot, key) + }) } pub fn release_devtools_document_lifecycle_wait_key( @@ -2410,30 +2355,25 @@ impl CdpConnection { let Some(owner_scope) = self.command_owner_scope_for_devtools_context(context) else { return false; }; - self.runtime_session_owner_slot_mut_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) - .is_ok_and(|slot| { - slot.page_slot_mut() - .release_renderer_document_lifecycle_waiter( - key.registration_id, - key.renderer_document, - key.renderer_epoch, - &key.frame_id, - &key.loader_id, - ) - }) + self.runtime_session_owner_slot_mut_for_owner(&owner_scope) + .is_ok_and(|slot| { + slot.page_slot_mut() + .release_renderer_document_lifecycle_waiter( + key.registration_id, + key.renderer_document, + key.renderer_epoch, + &key.frame_id, + &key.loader_id, + ) + }) } - pub(crate) fn accepts_document_body_completion_for_route( + pub(crate) fn accepts_document_body_completion_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, token: &DocumentNavigationToken, ) -> bool { - let Some((browser_context_id, target_id)) = - self.target_owner_identity_for_route(session_id, owner_route) + let Some((browser_context_id, target_id)) = self.target_owner_identity_for_owner(owner) else { return false; }; @@ -2451,8 +2391,7 @@ impl CdpConnection { owner: &CommandOwnerScope, loader_id: &str, ) { - let Some((browser_context_id, target_id)) = - self.target_owner_identity_for_route(owner.session_id(), owner.session_owner_route()) + let Some((browser_context_id, target_id)) = self.target_owner_identity_for_owner(owner) else { return; }; @@ -2522,32 +2461,27 @@ impl CdpConnection { })); } - pub(crate) fn background_navigation_completion_sender_for_route( + pub(crate) fn background_navigation_completion_sender_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option< tokio::sync::mpsc::UnboundedSender, > { - if !self.can_run_background_navigation_for_route(session_id, owner_route) { + if !self.can_run_background_navigation_for_owner(owner) { return None; } self.scheduler_hooks .background_navigation_completion_sender() } - fn can_run_background_navigation_for_route( - &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, - ) -> bool { + fn can_run_background_navigation_for_owner(&self, owner: &CommandOwnerScope) -> bool { if !self .scheduler_hooks .has_background_navigation_completion_sender() { return false; } - self.target_owner_identity_for_route(session_id, owner_route) + self.target_owner_identity_for_owner(owner) .is_some_and(|(_, target_id)| target_id.is_some()) } @@ -2693,7 +2627,7 @@ impl CdpConnection { engine: NavigationEngine, ) { let Some((browser_context_id, Some(target_id))) = - self.target_owner_identity_for_route(owner.session_id(), owner.session_owner_route()) + self.target_owner_identity_for_owner(owner) else { self.replace_standalone_navigation_engine(engine); return; @@ -2746,12 +2680,14 @@ impl CdpConnection { /// authority. pub(crate) fn publish_prepared_top_level_location_navigation_owner_action( &mut self, - session_id: Option<&str>, + owner: &CommandOwnerScope, page_owner: TargetPageResidenceIdentity, navigation: moli_core::page::RendererDocumentSourcedTopLevelLocationNavigation, ) { let action = TopLevelLocationNavigationOwnerAction::from_prepared( - self, session_id, page_owner, navigation, + owner.clone(), + page_owner, + navigation, ); self.publish_top_level_location_navigation_owner_action(action); } @@ -3753,12 +3689,12 @@ impl CdpConnection { self.exact_target_info_changed_event_plan_for_target_delta(target_id) } - pub(crate) fn target_info_changed_event_plan_for_session_owner( + pub(crate) fn target_info_changed_event_plan_for_owner( &mut self, - session_id: Option<&str>, + owner: &CommandOwnerScope, ) -> TargetEventPlan { let Some((browser_context_id, Some(target_id))) = - self.target_owner_identity_for_session(session_id) + self.target_owner_identity_for_owner(owner) else { return TargetEventPlan::default(); }; diff --git a/moli-protocol/src/conn/activity_source.rs b/moli-protocol/src/conn/activity_source.rs index d03d2d33be..874e38471e 100644 --- a/moli-protocol/src/conn/activity_source.rs +++ b/moli-protocol/src/conn/activity_source.rs @@ -35,18 +35,15 @@ impl CdpConnection { &mut self, session_id: Option<&str>, ) -> Option<(&mut NavigationEngine, &mut TargetRuntimeSlot)> { - self.activity_source_engine_and_runtime_slot_mut_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.activity_source_engine_and_runtime_slot_mut_for_owner(&owner) } - fn activity_source_engine_and_runtime_slot_mut_for_route( + fn activity_source_engine_and_runtime_slot_mut_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option<(&mut NavigationEngine, &mut TargetRuntimeSlot)> { - let route = match session_id { - Some(_) => self.session_route(session_id)?, - None => owner_route.cloned().unwrap_or(CdpSessionRoute::Browser), - }; + let route = owner.resolve_route(self)?; let (browser_context_id, target_id) = match &route { CdpSessionRoute::PageTarget { browser_context_id, @@ -74,23 +71,13 @@ impl CdpConnection { .navigation_engine_and_runtime_slot_mut() } - fn activity_source_engine_and_runtime_slot_mut_for_owner( - &mut self, - owner: &CommandOwnerScope, - ) -> Option<(&mut NavigationEngine, &mut TargetRuntimeSlot)> { - self.activity_source_engine_and_runtime_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - ) - } - pub(crate) fn start_child_frame_lifecycle_work_for_owner( &mut self, owner: CommandOwnerScope, timeout: std::time::Duration, ) -> Result { let storage = self - .navigation_load_inputs_for_route(owner.session_id(), owner.session_owner_route()) + .navigation_load_inputs_for_owner(&owner) .resource_storage_handles(); let Some((engine, slot)) = self.activity_source_engine_and_runtime_slot_mut_for_owner(&owner) diff --git a/moli-protocol/src/conn/bidi_channel_work.rs b/moli-protocol/src/conn/bidi_channel_work.rs index 06b843823f..a450141ba5 100644 --- a/moli-protocol/src/conn/bidi_channel_work.rs +++ b/moli-protocol/src/conn/bidi_channel_work.rs @@ -23,10 +23,7 @@ impl BidiChannelPageOwner { owner_scope: CommandOwnerScope, ) -> Option { Some(Self { - attachment: conn.target_page_protocol_attachment_identity_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - )?, + attachment: conn.target_page_protocol_attachment_identity_for_owner(&owner_scope)?, owner_scope, }) } @@ -234,7 +231,7 @@ mod tests { .expect("implicit owner must capture the scoped Page"); assert_eq!( - owner.command_owner().session_owner_route(), + owner.command_owner().explicit_route(), Some(&owner_route), "deferred work must retain its exact Page route" ); diff --git a/moli-protocol/src/conn/browser_context/emulation_owner.rs b/moli-protocol/src/conn/browser_context/emulation_owner.rs index ee3ab7fb8a..52fdd8217d 100644 --- a/moli-protocol/src/conn/browser_context/emulation_owner.rs +++ b/moli-protocol/src/conn/browser_context/emulation_owner.rs @@ -94,16 +94,16 @@ impl CdpConnection { session_id: Option<&str>, f: impl FnOnce(Option>), ) -> bool { - self.mutate_emulation_session_state_for_route(session_id, None, f) + let owner = crate::conn::CommandOwnerScope::capture(self, session_id); + self.mutate_emulation_session_state_for_owner(&owner, f) } - pub(crate) fn mutate_emulation_session_state_for_route( + pub(crate) fn mutate_emulation_session_state_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &crate::conn::CommandOwnerScope, f: impl FnOnce(Option>), ) -> bool { - self.with_target_session_owner_mut_for_route(session_id, owner_route, |owner| { + self.with_target_session_owner_mut_for_owner(owner, |owner| { owner.mutate_emulation_session_state(f) }) .unwrap_or(false) @@ -129,26 +129,24 @@ impl CdpConnection { .set_devtools_timezone_override(timezone_override) } - pub(crate) fn set_base_locale_override_for_route( + pub(crate) fn set_base_locale_override_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &crate::conn::CommandOwnerScope, locale_override: Option, ) -> bool { let fallback_identity = self.base_browser_identity.clone(); - self.target_session_owner_mut_for_route(session_id, owner_route) + self.target_session_owner_mut_for_owner(owner) .is_some_and(|mut owner| { owner.set_base_locale_override(locale_override, &fallback_identity) }) } - pub(crate) fn set_base_timezone_override_for_route( + pub(crate) fn set_base_timezone_override_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &crate::conn::CommandOwnerScope, timezone_override: Option, ) -> bool { - self.target_session_owner_mut_for_route(session_id, owner_route) + self.target_session_owner_mut_for_owner(owner) .is_some_and(|mut owner| owner.set_base_timezone_override(timezone_override)) } diff --git a/moli-protocol/src/conn/browser_context/fetch_owner.rs b/moli-protocol/src/conn/browser_context/fetch_owner.rs index 0f5017ec01..a778fa8a29 100644 --- a/moli-protocol/src/conn/browser_context/fetch_owner.rs +++ b/moli-protocol/src/conn/browser_context/fetch_owner.rs @@ -4,11 +4,12 @@ use crate::conn::state::{ TargetFetchConfig, TargetFetchOwner, TargetFetchSubresourceInterceptionSnapshot, }; use crate::conn::{ - CapturedBody, CompletedFetchResponseBodyStreamReadDispatch, FetchInterceptionPattern, - FetchRequestStage, InFlightSubresourceFetchRequest, PausedDocumentTransfer, - PendingFetchAuthNavigation, PendingFetchNavigation, PendingFetchResponseBodyStreamRead, - PendingFetchResponseBodyStreamReadStart, PendingSubresourceFetchAuthRequest, - PendingSubresourceFetchRequest, PendingSubresourceFetchResponseRequest, TargetRuntimeSlot, + CapturedBody, CommandOwnerScope, CompletedFetchResponseBodyStreamReadDispatch, + FetchInterceptionPattern, FetchRequestStage, InFlightSubresourceFetchRequest, + PausedDocumentTransfer, PendingFetchAuthNavigation, PendingFetchNavigation, + PendingFetchResponseBodyStreamRead, PendingFetchResponseBodyStreamReadStart, + PendingSubresourceFetchAuthRequest, PendingSubresourceFetchRequest, + PendingSubresourceFetchResponseRequest, TargetRuntimeSlot, }; use crate::devtools_runtime::{DevToolsNetworkInterceptId, DevToolsNetworkResourceType}; use crate::domains::network::TargetIoStreamRead; @@ -221,12 +222,11 @@ fn remove_network_intercept_from_browser_context( } impl CdpConnection { - pub(crate) fn target_fetch_subresource_interception_snapshot_for_route( + pub(crate) fn target_fetch_subresource_interception_snapshot_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - self.target_session_owner_aggregate_fetch_config_for_route(session_id, owner_route) + self.target_session_owner_aggregate_fetch_config_for_owner(owner) .map(|config| config.subresource_interception_snapshot()) } @@ -238,40 +238,37 @@ impl CdpConnection { .map(|config| config.subresource_interception_snapshot()) } - pub(crate) fn target_fetch_event_session_id_for_route( + pub(crate) fn target_fetch_event_session_id_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - self.target_session_owner_aggregate_fetch_config_for_route(session_id, owner_route) + self.target_session_owner_aggregate_fetch_config_for_owner(owner) .and_then(|config| config.session_id().map(str::to_owned)) } - pub(crate) fn target_fetch_handle_auth_requests_for_route( + pub(crate) fn target_fetch_handle_auth_requests_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> bool { - self.target_session_owner_aggregate_fetch_config_for_route(session_id, owner_route) + self.target_session_owner_aggregate_fetch_config_for_owner(owner) .is_some_and(|config| config.handle_auth_requests()) } - pub(crate) fn target_fetch_matches_auth_required_for_route( + pub(crate) fn target_fetch_matches_auth_required_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, url: &url::Url, ) -> bool { - self.target_session_owner_aggregate_fetch_config_for_route(session_id, owner_route) + self.target_session_owner_aggregate_fetch_config_for_owner(owner) .is_some_and(|config| config.matches_auth_required(url)) } - pub(crate) fn target_fetch_matching_auth_required_network_intercepts_for_session_owner( + pub(crate) fn target_fetch_matching_auth_required_network_intercepts_for_owner( &self, - session_id: Option<&str>, + owner: &CommandOwnerScope, url: &url::Url, ) -> Vec { - self.target_session_owner_aggregate_fetch_config(session_id) + self.target_session_owner_aggregate_fetch_config_for_owner(owner) .map(|config| config.matching_auth_required_network_intercepts(url)) .unwrap_or_default() } @@ -317,15 +314,14 @@ impl CdpConnection { } } - pub(crate) fn allocate_pending_subresource_fetch_request_ids_for_route( + pub(crate) fn allocate_pending_subresource_fetch_request_ids_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Result<(String, String), String> { let mut network_request_id_allocator = std::mem::take(&mut self.network_request_id_allocator); let result = self - .runtime_session_owner_slot_mut_for_route(session_id, owner_route) + .runtime_session_owner_slot_mut_for_owner(owner) .map(|runtime_slot| { runtime_slot .request_id_allocator() @@ -337,12 +333,11 @@ impl CdpConnection { result } - pub(crate) fn allocate_fetch_navigation_request_id_for_route( + pub(crate) fn allocate_fetch_navigation_request_id_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Result { - self.runtime_session_owner_slot_mut_for_route(session_id, owner_route) + self.runtime_session_owner_slot_mut_for_owner(owner) .map(|runtime_slot| { runtime_slot .request_id_allocator() @@ -367,17 +362,16 @@ impl CdpConnection { session_id: Option<&str>, body: CapturedBody, ) -> Result { - self.open_io_stream_body_source_for_route(session_id, None, body) + let owner = CommandOwnerScope::capture(self, session_id); + self.open_io_stream_body_source_for_owner(&owner, body) } - pub(crate) fn open_io_stream_body_source_for_route( + pub(crate) fn open_io_stream_body_source_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, body: CapturedBody, ) -> Result { - let Some(mut owner) = self.target_session_owner_mut_for_route(session_id, owner_route) - else { + let Some(mut owner) = self.target_session_owner_mut_for_owner(owner) else { return Err("NoDocumentLoaded".to_owned()); }; owner.open_scoped_io_stream_body_source(body) @@ -404,17 +398,14 @@ impl CdpConnection { .read_io_stream(handle, offset, size) } - pub(crate) fn register_synthetic_websocket_request_for_route( + pub(crate) fn register_synthetic_websocket_request_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, request_id: String, network_request_id: String, socket_id: u64, ) -> bool { - let Ok(runtime_slot) = - self.runtime_session_owner_slot_mut_for_route(session_id, owner_route) - else { + let Ok(runtime_slot) = self.runtime_session_owner_slot_mut_for_owner(owner) else { return false; }; runtime_slot.register_synthetic_websocket_request( @@ -430,16 +421,16 @@ impl CdpConnection { session_id: Option<&str>, request_id: &str, ) -> Option { - self.synthetic_websocket_socket_id_for_route(session_id, None, request_id) + let owner = CommandOwnerScope::capture(self, session_id); + self.synthetic_websocket_socket_id_for_owner(&owner, request_id) } - pub(crate) fn synthetic_websocket_socket_id_for_route( + pub(crate) fn synthetic_websocket_socket_id_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, request_id: &str, ) -> Option { - self.runtime_session_owner_slot_for_route(session_id, owner_route) + self.runtime_session_owner_slot_for_owner(owner) .ok() .and_then(|runtime_slot| { runtime_slot.synthetic_websocket_socket_id_for_request(request_id) @@ -456,75 +447,67 @@ impl CdpConnection { pub(crate) fn pending_subresource_fetch_request_residence_is_current( &self, - session_id: Option<&str>, pending: &PendingSubresourceFetchRequest, ) -> bool { - pending.installed_page_owner().is_none_or(|owner| { - self.target_page_residence_identity_is_current_for_session(session_id, owner) - }) + pending + .installed_page_owner() + .is_none_or(|owner| self.target_page_residence_identity_is_current(owner)) } fn installed_subresource_fetch_request_is_current( &self, - session_id: Option<&str>, pending: &PendingSubresourceFetchRequest, ) -> bool { - pending.installed_page_owner().is_some_and(|owner| { - self.target_page_residence_identity_is_current_for_session(session_id, owner) - }) + pending + .installed_page_owner() + .is_some_and(|owner| self.target_page_residence_identity_is_current(owner)) } - pub(crate) fn claim_subresource_continue_request_for_route( + pub(crate) fn claim_subresource_continue_request_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, expected_page_owner: &crate::conn::TargetPageResidenceIdentity, internal_id: u64, allow_pending_completion: bool, ) -> Option { - if !self - .target_page_residence_identity_is_current_for_session(session_id, expected_page_owner) - { + if !self.target_page_residence_identity_is_current(expected_page_owner) { return None; } - self.target_session_owner_mut_for_route(session_id, owner_route)? + self.target_session_owner_mut_for_owner(owner)? .claim_subresource_continue_request( expected_page_owner, internal_id, - session_id, + owner.session_id(), allow_pending_completion, ) } - pub(crate) fn consume_pending_request_action_for_route( + pub(crate) fn consume_pending_request_action_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, request_id: &str, ) -> Option> { - self.target_session_owner_mut_for_route(session_id, owner_route)? + self.target_session_owner_mut_for_owner(owner)? .consume_pending_request_action(request_id) } - pub(crate) fn take_pending_fetch_navigation_for_route( + pub(crate) fn take_pending_fetch_navigation_for_owner( &mut self, - owner_session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, action_session_id: Option<&str>, request_id: &str, ) -> Option { - self.target_session_owner_mut_for_route(owner_session_id, owner_route)? + self.target_session_owner_mut_for_owner(owner)? .take_pending_fetch_navigation_for_action_session(request_id, action_session_id) } - pub(crate) fn take_pending_fetch_auth_navigation_for_route( + pub(crate) fn take_pending_fetch_auth_navigation_for_owner( &mut self, - owner_session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, action_session_id: Option<&str>, request_id: &str, ) -> Option { - self.target_session_owner_mut_for_route(owner_session_id, owner_route)? + self.target_session_owner_mut_for_owner(owner)? .take_pending_fetch_auth_navigation_for_action_session(request_id, action_session_id) } @@ -534,31 +517,31 @@ impl CdpConnection { request_id: String, pending: PendingFetchAuthNavigation, ) -> bool { - self.register_pending_fetch_auth_navigation_for_route(session_id, None, request_id, pending) + let owner = CommandOwnerScope::capture(self, session_id); + self.register_pending_fetch_auth_navigation_for_owner(&owner, request_id, pending) } - pub(crate) fn register_pending_fetch_auth_navigation_for_route( + pub(crate) fn register_pending_fetch_auth_navigation_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, request_id: String, pending: PendingFetchAuthNavigation, ) -> bool { - self.target_session_owner_mut_for_route(session_id, owner_route) + self.target_session_owner_mut_for_owner(owner) .is_some_and(|mut owner| { owner.register_pending_fetch_auth_navigation(request_id, pending) }) } - pub(crate) fn register_pending_fetch_response_navigation_for_session_owner( + pub(crate) fn register_pending_fetch_response_navigation_for_owner( &mut self, - session_id: Option<&str>, + owner: &CommandOwnerScope, request_id: String, document_navigation_token: Option, navigation: crate::conn::NavigationDispatchState, body: crate::conn::DocumentBodySource, ) -> bool { - self.target_session_owner_mut(session_id) + self.target_session_owner_mut_for_owner(owner) .is_some_and(|mut owner| { owner.register_pending_fetch_response_navigation( request_id, @@ -569,58 +552,53 @@ impl CdpConnection { }) } - pub(crate) fn take_pending_fetch_response_transfer_for_terminal_action_for_route( + pub(crate) fn take_pending_fetch_response_transfer_for_terminal_action_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, request_id: &str, ) -> Option { - self.target_session_owner_mut_for_route(session_id, owner_route)? + self.target_session_owner_mut_for_owner(owner)? .take_pending_fetch_response_transfer_for_terminal_action(request_id) } - pub(crate) fn take_pending_fetch_response_transfer_for_body_read_for_route( + pub(crate) fn take_pending_fetch_response_transfer_for_body_read_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, request_id: &str, ) -> Option { - self.target_session_owner_mut_for_route(session_id, owner_route)? + self.target_session_owner_mut_for_owner(owner)? .take_pending_fetch_response_transfer(request_id) } - pub(crate) fn register_pending_fetch_response_transfer_for_route( + pub(crate) fn register_pending_fetch_response_transfer_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, request_id: String, transfer: PausedDocumentTransfer, ) -> bool { - self.target_session_owner_mut_for_route(session_id, owner_route) + self.target_session_owner_mut_for_owner(owner) .is_some_and(|mut owner| { owner.register_pending_fetch_response_transfer(request_id, transfer) }) } - pub(crate) fn pending_subresource_fetch_response_request_for_route( + pub(crate) fn pending_subresource_fetch_response_request_for_owner( &mut self, - owner_session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, action_session_id: Option<&str>, request_id: &str, ) -> Option { - self.target_session_owner_mut_for_route(owner_session_id, owner_route)? + self.target_session_owner_mut_for_owner(owner)? .pending_subresource_fetch_response_request(request_id, action_session_id) } - pub(crate) fn mark_pending_subresource_fetch_response_body_taken_as_stream_for_route( + pub(crate) fn mark_pending_subresource_fetch_response_body_taken_as_stream_for_owner( &mut self, - owner_session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, action_session_id: Option<&str>, request_id: &str, ) -> bool { - self.target_session_owner_mut_for_route(owner_session_id, owner_route) + self.target_session_owner_mut_for_owner(owner) .is_some_and(|mut owner| { owner.mark_pending_subresource_fetch_response_body_taken_as_stream( request_id, @@ -780,81 +758,70 @@ impl CdpConnection { let pending = self .target_session_owner_mut(session_id)? .take_pending_subresource_fetch_request(request_id, session_id)?; - self.pending_subresource_fetch_request_residence_is_current(session_id, &pending) + self.pending_subresource_fetch_request_residence_is_current(&pending) .then_some(pending) } - pub(crate) fn take_pending_subresource_fetch_request_for_route( + pub(crate) fn take_pending_subresource_fetch_request_for_owner( &mut self, - owner_session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, action_session_id: Option<&str>, request_id: &str, ) -> Option { let pending = self - .target_session_owner_mut_for_route(owner_session_id, owner_route)? + .target_session_owner_mut_for_owner(owner)? .take_pending_subresource_fetch_request(request_id, action_session_id)?; - self.pending_subresource_fetch_request_residence_is_current(owner_session_id, &pending) + self.pending_subresource_fetch_request_residence_is_current(&pending) .then_some(pending) } - pub(crate) fn take_pending_subresource_fetch_auth_request_for_route( + pub(crate) fn take_pending_subresource_fetch_auth_request_for_owner( &mut self, - owner_session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, action_session_id: Option<&str>, request_id: &str, ) -> Option { let pending = self - .target_session_owner_mut_for_route(owner_session_id, owner_route)? + .target_session_owner_mut_for_owner(owner)? .take_pending_subresource_fetch_auth_request(request_id, action_session_id)?; - self.target_page_residence_identity_is_current_for_session( - owner_session_id, - &pending.page_owner, - ) - .then_some(pending) + self.target_page_residence_identity_is_current(&pending.page_owner) + .then_some(pending) } - pub(crate) fn take_pending_subresource_fetch_response_request_for_route( + pub(crate) fn take_pending_subresource_fetch_response_request_for_owner( &mut self, - owner_session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, action_session_id: Option<&str>, request_id: &str, ) -> Option { let pending = self - .target_session_owner_mut_for_route(owner_session_id, owner_route)? + .target_session_owner_mut_for_owner(owner)? .take_pending_subresource_fetch_response_request(request_id, action_session_id)?; - self.target_page_residence_identity_is_current_for_session( - owner_session_id, - &pending.page_owner, - ) - .then_some(pending) + self.target_page_residence_identity_is_current(&pending.page_owner) + .then_some(pending) } - pub(crate) fn take_in_flight_subresource_fetch_request_for_route( + pub(crate) fn take_in_flight_subresource_fetch_request_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, internal_id: u64, ) -> Option { let in_flight = self - .target_session_owner_mut_for_route(session_id, owner_route)? + .target_session_owner_mut_for_owner(owner)? .take_in_flight_subresource_fetch_request(internal_id)?; - self.installed_subresource_fetch_request_is_current(session_id, &in_flight.pending) + self.installed_subresource_fetch_request_is_current(&in_flight.pending) .then_some(in_flight) } - pub(crate) fn in_flight_subresource_fetch_request_id_for_route( + pub(crate) fn in_flight_subresource_fetch_request_id_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, internal_id: u64, ) -> Option { let (request_id, page_owner) = self - .target_session_owner_mut_for_route(session_id, owner_route)? + .target_session_owner_mut_for_owner(owner)? .in_flight_subresource_fetch_request_identity(internal_id)?; - self.target_page_residence_identity_is_current_for_session(session_id, &page_owner) + self.target_page_residence_identity_is_current(&page_owner) .then_some(request_id) } @@ -864,70 +831,54 @@ impl CdpConnection { request_id: String, pending: PendingSubresourceFetchRequest, ) -> bool { - self.register_pending_subresource_fetch_request_for_route( - session_id, None, request_id, pending, - ) + let owner = CommandOwnerScope::capture(self, session_id); + self.register_pending_subresource_fetch_request_for_owner(&owner, request_id, pending) } - pub(crate) fn register_pending_subresource_fetch_request_for_route( + pub(crate) fn register_pending_subresource_fetch_request_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, request_id: String, pending: PendingSubresourceFetchRequest, ) -> bool { - if !self.pending_subresource_fetch_request_residence_is_current(session_id, &pending) { + if !self.pending_subresource_fetch_request_residence_is_current(&pending) { return false; } - self.record_pending_subresource_network_request_identity_for_route( - session_id, - owner_route, - &pending, - ); - self.target_session_owner_mut_for_route(session_id, owner_route) + self.record_pending_subresource_network_request_identity_for_owner(owner, &pending); + self.target_session_owner_mut_for_owner(owner) .is_some_and(|mut owner| { owner.register_pending_subresource_fetch_request(request_id, pending) }) } - pub(crate) fn register_in_flight_subresource_fetch_request_for_route( + pub(crate) fn register_in_flight_subresource_fetch_request_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, request_id: Option, pending: PendingSubresourceFetchRequest, ) -> bool { - if !self.installed_subresource_fetch_request_is_current(session_id, &pending) { + if !self.installed_subresource_fetch_request_is_current(&pending) { return false; } - self.record_pending_subresource_network_request_identity_for_route( - session_id, - owner_route, - &pending, - ); - self.target_session_owner_mut_for_route(session_id, owner_route) + self.record_pending_subresource_network_request_identity_for_owner(owner, &pending); + self.target_session_owner_mut_for_owner(owner) .is_some_and(|mut owner| { owner.register_in_flight_subresource_fetch_request(request_id, pending) }) } - pub(crate) fn register_in_flight_response_stage_subresource_fetch_request_for_route( + pub(crate) fn register_in_flight_response_stage_subresource_fetch_request_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, request_id: Option, pending: PendingSubresourceFetchRequest, response_stage_blocked_intercepts: Vec, ) -> bool { - if !self.installed_subresource_fetch_request_is_current(session_id, &pending) { + if !self.installed_subresource_fetch_request_is_current(&pending) { return false; } - self.record_pending_subresource_network_request_identity_for_route( - session_id, - owner_route, - &pending, - ); - self.target_session_owner_mut_for_route(session_id, owner_route) + self.record_pending_subresource_network_request_identity_for_owner(owner, &pending); + self.target_session_owner_mut_for_owner(owner) .is_some_and(|mut owner| { owner.register_in_flight_response_stage_subresource_fetch_request( request_id, @@ -938,22 +889,17 @@ impl CdpConnection { }) } - pub(crate) fn register_in_flight_deferred_response_stage_subresource_fetch_request_for_route( + pub(crate) fn register_in_flight_deferred_response_stage_subresource_fetch_request_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, request_id: Option, pending: PendingSubresourceFetchRequest, ) -> bool { - if !self.installed_subresource_fetch_request_is_current(session_id, &pending) { + if !self.installed_subresource_fetch_request_is_current(&pending) { return false; } - self.record_pending_subresource_network_request_identity_for_route( - session_id, - owner_route, - &pending, - ); - self.target_session_owner_mut_for_route(session_id, owner_route) + self.record_pending_subresource_network_request_identity_for_owner(owner, &pending); + self.target_session_owner_mut_for_owner(owner) .is_some_and(|mut owner| { owner.register_in_flight_subresource_fetch_request_with_response_match_policy( request_id, @@ -969,29 +915,21 @@ impl CdpConnection { request_id: String, pending: PendingSubresourceFetchAuthRequest, ) -> bool { - self.register_pending_subresource_fetch_auth_request_for_route( - session_id, None, request_id, pending, - ) + let owner = CommandOwnerScope::capture(self, session_id); + self.register_pending_subresource_fetch_auth_request_for_owner(&owner, request_id, pending) } - pub(crate) fn register_pending_subresource_fetch_auth_request_for_route( + pub(crate) fn register_pending_subresource_fetch_auth_request_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, request_id: String, pending: PendingSubresourceFetchAuthRequest, ) -> bool { - if !self - .target_page_residence_identity_is_current_for_session(session_id, &pending.page_owner) - { + if !self.target_page_residence_identity_is_current(&pending.page_owner) { return false; } - self.record_pending_subresource_auth_network_request_identity_for_route( - session_id, - owner_route, - &pending, - ); - self.target_session_owner_mut_for_route(session_id, owner_route) + self.record_pending_subresource_auth_network_request_identity_for_owner(owner, &pending); + self.target_session_owner_mut_for_owner(owner) .is_some_and(|mut owner| { owner.register_pending_subresource_fetch_auth_request(request_id, pending) }) @@ -1003,46 +941,39 @@ impl CdpConnection { request_id: String, pending: PendingSubresourceFetchResponseRequest, ) -> bool { - self.register_pending_subresource_fetch_response_request_for_route( - session_id, None, request_id, pending, + let owner = CommandOwnerScope::capture(self, session_id); + self.register_pending_subresource_fetch_response_request_for_owner( + &owner, request_id, pending, ) } - pub(crate) fn register_pending_subresource_fetch_response_request_for_route( + pub(crate) fn register_pending_subresource_fetch_response_request_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, request_id: String, pending: PendingSubresourceFetchResponseRequest, ) -> bool { - if !self - .target_page_residence_identity_is_current_for_session(session_id, &pending.page_owner) - { + if !self.target_page_residence_identity_is_current(&pending.page_owner) { return false; } - self.record_pending_subresource_response_network_request_identity_for_route( - session_id, - owner_route, - &pending, + self.record_pending_subresource_response_network_request_identity_for_owner( + owner, &pending, ); - self.target_session_owner_mut_for_route(session_id, owner_route) + self.target_session_owner_mut_for_owner(owner) .is_some_and(|mut owner| { owner.register_pending_subresource_fetch_response_request(request_id, pending) }) } - fn record_pending_subresource_network_request_identity_for_route( + fn record_pending_subresource_network_request_identity_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, pending: &PendingSubresourceFetchRequest, ) { let Some(handle) = pending.network_request_handle else { return; }; - if let Ok(runtime_slot) = - self.runtime_session_owner_slot_mut_for_route(session_id, owner_route) - { + if let Ok(runtime_slot) = self.runtime_session_owner_slot_mut_for_owner(owner) { runtime_slot.record_subresource_request_id_for_handle_if_absent( handle, pending.network_request_id.clone(), @@ -1050,18 +981,15 @@ impl CdpConnection { } } - fn record_pending_subresource_auth_network_request_identity_for_route( + fn record_pending_subresource_auth_network_request_identity_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, pending: &PendingSubresourceFetchAuthRequest, ) { let Some(handle) = pending.network_request_handle else { return; }; - if let Ok(runtime_slot) = - self.runtime_session_owner_slot_mut_for_route(session_id, owner_route) - { + if let Ok(runtime_slot) = self.runtime_session_owner_slot_mut_for_owner(owner) { runtime_slot.record_subresource_request_id_for_handle_if_absent( handle, pending.network_request_id.clone(), @@ -1069,18 +997,15 @@ impl CdpConnection { } } - fn record_pending_subresource_response_network_request_identity_for_route( + fn record_pending_subresource_response_network_request_identity_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, pending: &PendingSubresourceFetchResponseRequest, ) { let Some(handle) = pending.network_request_handle else { return; }; - if let Ok(runtime_slot) = - self.runtime_session_owner_slot_mut_for_route(session_id, owner_route) - { + if let Ok(runtime_slot) = self.runtime_session_owner_slot_mut_for_owner(owner) { runtime_slot.record_subresource_request_id_for_handle_if_absent( handle, pending.network_request_id.clone(), @@ -1094,22 +1019,21 @@ impl CdpConnection { handle_auth_requests: bool, patterns: Vec, ) -> Result, String> { - self.start_enable_fetch_for_route(session_id, None, handle_auth_requests, patterns) + let owner = CommandOwnerScope::capture(self, session_id); + self.start_enable_fetch_for_owner(&owner, handle_auth_requests, patterns) } - pub(crate) fn start_enable_fetch_for_route( + pub(crate) fn start_enable_fetch_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + command_owner: &CommandOwnerScope, handle_auth_requests: bool, patterns: Vec, ) -> Result, String> { - let Some(mut owner) = self.target_session_owner_mut_for_route(session_id, owner_route) - else { + let Some(mut owner) = self.target_session_owner_mut_for_owner(command_owner) else { return Err("BrowserContextNotLoaded".to_owned()); }; let (subresource_enabled, subresource_resource_type) = owner.configure_fetch( - session_id.map(str::to_owned), + command_owner.session_id().map(str::to_owned), handle_auth_requests, patterns, ); @@ -1125,18 +1049,16 @@ impl CdpConnection { } #[allow(clippy::too_many_arguments)] - pub(crate) fn start_add_network_intercept_for_route( + pub(crate) fn start_add_network_intercept_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + command_owner: &CommandOwnerScope, intercept_session_id: Option, intercept_id: String, handle_auth_requests: bool, auth_url_patterns: Vec, patterns: Vec, ) -> Result, String> { - let Some(mut owner) = self.target_session_owner_mut_for_route(session_id, owner_route) - else { + let Some(mut owner) = self.target_session_owner_mut_for_owner(command_owner) else { return Err("BrowserContextNotLoaded".to_owned()); }; let (subresource_enabled, subresource_resource_type) = owner.add_network_intercept( @@ -1157,15 +1079,13 @@ impl CdpConnection { .map_err(|error| format!("failed to update page fetch interception: {error}")) } - pub(crate) fn start_remove_network_intercept_for_route( + pub(crate) fn start_remove_network_intercept_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + command_owner: &CommandOwnerScope, intercept_id: &str, allow_global_lookup: bool, ) -> Result, String> { - let Some(mut owner) = self.target_session_owner_mut_for_route(session_id, owner_route) - else { + let Some(mut owner) = self.target_session_owner_mut_for_owner(command_owner) else { return Err("BrowserContextNotLoaded".to_owned()); }; let Some((subresource_enabled, subresource_resource_type)) = @@ -1217,13 +1137,13 @@ impl CdpConnection { )>, String, > { - self.start_disable_fetch_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.start_disable_fetch_for_owner(&owner) } - pub(crate) fn start_disable_fetch_for_route( + pub(crate) fn start_disable_fetch_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + command_owner: &CommandOwnerScope, ) -> Result< Option<( SessionOwnerPendingFetchState, @@ -1231,12 +1151,12 @@ impl CdpConnection { )>, String, > { - let Some(mut owner) = self.target_session_owner_mut_for_route(session_id, owner_route) - else { + let Some(mut owner) = self.target_session_owner_mut_for_owner(command_owner) else { return Ok(None); }; let (pending, (subresource_enabled, subresource_resource_type), page_update_required) = - owner.reset_fetch_config_for_session_and_drain_pending_state(session_id); + owner + .reset_fetch_config_for_session_and_drain_pending_state(command_owner.session_id()); let page_command = if page_update_required && let Some(page) = owner.runtime_slot_mut().loaded_page_mut() { @@ -1253,13 +1173,12 @@ impl CdpConnection { Ok(Some((pending, page_command))) } - pub(crate) fn take_pending_fetch_state_for_route( + pub(crate) fn take_pending_fetch_state_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { Some( - self.target_session_owner_mut_for_route(session_id, owner_route)? + self.target_session_owner_mut_for_owner(owner)? .drain_fetch_pending_state(), ) } diff --git a/moli-protocol/src/conn/browser_context/network_owner.rs b/moli-protocol/src/conn/browser_context/network_owner.rs index ca65a66feb..dc2d12df96 100644 --- a/moli-protocol/src/conn/browser_context/network_owner.rs +++ b/moli-protocol/src/conn/browser_context/network_owner.rs @@ -356,23 +356,17 @@ impl CdpConnection { data_type: DevToolsNetworkDataType, encoded_data_size: usize, ) -> Vec { - self.network_data_collector_ids_for_route_body( - session_id, - None, - data_type, - encoded_data_size, - ) + let owner = crate::conn::CommandOwnerScope::capture(self, session_id); + self.network_data_collector_ids_for_owner_body(&owner, data_type, encoded_data_size) } - pub(crate) fn network_data_collector_ids_for_route_body( + pub(crate) fn network_data_collector_ids_for_owner_body( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &crate::conn::CommandOwnerScope, data_type: DevToolsNetworkDataType, encoded_data_size: usize, ) -> Vec { - let Some((browser_context_id, target_id)) = - self.target_owner_identity_for_route(session_id, owner_route) + let Some((browser_context_id, target_id)) = self.target_owner_identity_for_owner(owner) else { return Vec::new(); }; @@ -445,10 +439,9 @@ impl CdpConnection { .is_ok_and(|runtime_slot| runtime_slot.has_network_event_listeners()) } - pub(crate) fn network_backlog_prepared_delivery_for_route( + pub(crate) fn network_backlog_prepared_delivery_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &crate::conn::CommandOwnerScope, trigger_session_id: Option<&str>, primary_session_id: Option<&str>, preferred_request_id: Option>, @@ -456,7 +449,7 @@ impl CdpConnection { let mut network_request_id_allocator = std::mem::take(&mut self.network_request_id_allocator); let result = self - .runtime_session_owner_slot_mut_for_route(session_id, owner_route) + .runtime_session_owner_slot_mut_for_owner(owner) .ok() .map(|runtime_slot| { runtime_slot.network_backlog_prepared_delivery( @@ -490,10 +483,9 @@ impl CdpConnection { result } - pub(crate) fn pending_network_backlog_delivery_snapshot_for_route( + pub(crate) fn pending_network_backlog_delivery_snapshot_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &crate::conn::CommandOwnerScope, trigger_session_id: Option<&str>, primary_session_id: Option<&str>, preferred_request_id: Option>, @@ -501,7 +493,7 @@ impl CdpConnection { let mut network_request_id_allocator = std::mem::take(&mut self.network_request_id_allocator); let result = self - .runtime_session_owner_slot_mut_for_route(session_id, owner_route) + .runtime_session_owner_slot_mut_for_owner(owner) .ok() .and_then(|runtime_slot| { runtime_slot.pending_network_backlog_delivery_snapshot( @@ -519,51 +511,49 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> Vec> { - self.network_event_session_ids_for_route(session_id, None) + let owner = crate::conn::CommandOwnerScope::capture(self, session_id); + self.network_event_session_ids_for_owner(&owner) } - pub(crate) fn network_event_session_ids_for_route( + pub(crate) fn network_event_session_ids_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &crate::conn::CommandOwnerScope, ) -> Vec> { - let Ok(runtime_slot) = self.runtime_session_owner_slot_for_route(session_id, owner_route) - else { - return vec![session_id.map(str::to_owned)]; + let Ok(runtime_slot) = self.runtime_session_owner_slot_for_owner(owner) else { + return vec![owner.session_id().map(str::to_owned)]; }; - let primary_session_id = - self.runtime_session_owner_primary_session_id_for_route(session_id, owner_route); - runtime_slot.network_event_session_ids(session_id, primary_session_id.as_deref()) + let primary_session_id = self.runtime_session_owner_primary_session_id_for_owner(owner); + runtime_slot.network_event_session_ids(owner.session_id(), primary_session_id.as_deref()) } pub(crate) fn enable_network_listener_for_session_owner( &mut self, session_id: Option<&str>, ) -> bool { - self.set_network_listener_enabled_for_route(session_id, None, true) + let owner = crate::conn::CommandOwnerScope::capture(self, session_id); + self.set_network_listener_enabled_for_owner(&owner, true) } - fn set_network_listener_enabled_for_route( + fn set_network_listener_enabled_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &crate::conn::CommandOwnerScope, enabled: bool, ) -> bool { - if let Some(session_id) = session_id + if let Some(session_id) = owner.session_id() && let Some(target) = self.service_worker_target_for_session_mut(Some(session_id)) { return target.set_network_enabled(session_id, enabled); } - if let Some(session_id) = session_id + if let Some(session_id) = owner.session_id() && let Some(target) = self.dedicated_worker_target_for_session_mut(Some(session_id)) { return target.set_network_enabled(session_id, enabled); } - self.with_target_session_owner_mut_for_route(session_id, owner_route, |owner| { + self.with_target_session_owner_mut_for_owner(owner, |resolved| { if enabled { - owner.enable_listener() + resolved.enable_listener() } else { - owner.disable_listener() + resolved.disable_listener() } }) .unwrap_or(false) @@ -573,14 +563,20 @@ impl CdpConnection { let Some(route) = self.target_session_route_for_target_id(target_id) else { return false; }; - self.set_network_listener_enabled_for_route(None, Some(&route), true) + self.set_network_listener_enabled_for_owner( + &crate::conn::CommandOwnerScope::for_route(route), + true, + ) } pub fn disable_network_listener_for_target(&mut self, target_id: &str) -> bool { let Some(route) = self.target_session_route_for_target_id(target_id) else { return false; }; - self.set_network_listener_enabled_for_route(None, Some(&route), false) + self.set_network_listener_enabled_for_owner( + &crate::conn::CommandOwnerScope::for_route(route), + false, + ) } pub(crate) fn set_global_cache_disabled(&mut self, cache_disabled: bool) { @@ -611,7 +607,8 @@ impl CdpConnection { &mut self, session_id: Option<&str>, ) -> bool { - self.set_network_listener_enabled_for_route(session_id, None, false) + let owner = crate::conn::CommandOwnerScope::capture(self, session_id); + self.set_network_listener_enabled_for_owner(&owner, false) } pub(crate) fn start_set_cache_disabled_for_session_owner( @@ -676,13 +673,12 @@ impl CdpConnection { owner.start_set_extra_http_headers(extra_headers) } - pub(crate) fn start_set_target_extra_http_headers_for_route( + pub(crate) fn start_set_target_extra_http_headers_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + command_owner: &crate::conn::CommandOwnerScope, extra_headers: Vec<(String, String)>, ) -> Result, String> { - let Some(owner) = self.target_session_owner_mut_for_route(session_id, owner_route) else { + let Some(owner) = self.target_session_owner_mut_for_owner(command_owner) else { return Err("BrowserContextNotLoaded".to_owned()); }; owner.start_set_target_extra_http_headers(extra_headers) @@ -708,10 +704,9 @@ impl CdpConnection { owner.start_replay_effective_network_request_policy() } - pub(crate) fn start_set_base_user_agent_override_for_route( + pub(crate) fn start_set_base_user_agent_override_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + command_owner: &crate::conn::CommandOwnerScope, user_agent: Option, ) -> Result, String> { let browser_identity = user_agent.as_ref().map(|user_agent| { @@ -720,22 +715,21 @@ impl CdpConnection { self.base_browser_identity.accept_language(), ) }); - if owner_route.is_none() - && let Some(result) = - self.start_set_non_page_browser_identity_override(session_id, browser_identity) - { + if let Some(result) = self.start_set_non_page_browser_identity_override( + command_owner.session_id(), + browser_identity, + ) { return result; } let fallback_identity = self.base_browser_identity.clone(); - let Some(mut owner) = self.target_session_owner_mut_for_route(session_id, owner_route) - else { + let Some(mut owner) = self.target_session_owner_mut_for_owner(command_owner) else { return Err("BrowserContextNotLoaded".to_owned()); }; if !owner.set_base_user_agent_override(user_agent, &fallback_identity) { return Err("BrowserContextNotLoaded".to_owned()); } - self.start_rebuild_resource_runtime_for_route(session_id, owner_route) + self.start_rebuild_resource_runtime_for_owner(command_owner) } fn start_set_non_page_browser_identity_override( @@ -833,9 +827,9 @@ impl CdpConnection { upload_throughput: f64, connection_type: Option, ) -> Result, String> { - self.start_set_emulated_network_conditions_for_route( - session_id, - None, + let owner = crate::conn::CommandOwnerScope::capture(self, session_id); + self.start_set_emulated_network_conditions_for_owner( + &owner, offline, latency, download_throughput, @@ -844,17 +838,16 @@ impl CdpConnection { ) } - pub(crate) fn start_set_emulated_network_conditions_for_route( + pub(crate) fn start_set_emulated_network_conditions_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + command_owner: &crate::conn::CommandOwnerScope, offline: bool, latency: f64, download_throughput: f64, upload_throughput: f64, connection_type: Option, ) -> Result, String> { - let Some(owner) = self.target_session_owner_mut_for_route(session_id, owner_route) else { + let Some(owner) = self.target_session_owner_mut_for_owner(command_owner) else { return Err("BrowserContextNotLoaded".to_owned()); }; owner.start_set_emulated_network_conditions( @@ -921,13 +914,19 @@ mod tests { conn.browser_context = Some(browser_context); let (active_fetch_id, active_network_request_id) = conn - .allocate_pending_subresource_fetch_request_ids_for_route(Some("SID-active"), None) + .allocate_pending_subresource_fetch_request_ids_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-active"), + ) .expect("active owner should allocate request ids"); let (background_fetch_id, background_network_request_id) = conn - .allocate_pending_subresource_fetch_request_ids_for_route(Some("SID-background"), None) + .allocate_pending_subresource_fetch_request_ids_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-background"), + ) .expect("background owner should allocate request ids"); let (second_active_fetch_id, second_active_network_request_id) = conn - .allocate_pending_subresource_fetch_request_ids_for_route(Some("SID-active"), None) + .allocate_pending_subresource_fetch_request_ids_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-active"), + ) .expect("active owner should allocate a second request id"); assert_eq!(active_fetch_id, "INT-SUB-1"); diff --git a/moli-protocol/src/conn/browser_context/page_owner.rs b/moli-protocol/src/conn/browser_context/page_owner.rs index f71068ffd8..8d3e370832 100644 --- a/moli-protocol/src/conn/browser_context/page_owner.rs +++ b/moli-protocol/src/conn/browser_context/page_owner.rs @@ -475,7 +475,8 @@ impl CdpConnection { &mut self, session_id: Option<&str>, ) -> SessionOwnerAuditsEnableResult { - let accepts_without_target = self.accepts_unmaterialized_page_command(session_id, None); + let accepts_without_target = + self.accepts_unmaterialized_page_command_for_session(session_id); self.with_target_session_owner_mut(session_id, |owner| owner.enable_audits()) .unwrap_or({ if accepts_without_target { @@ -487,7 +488,8 @@ impl CdpConnection { } pub(crate) fn disable_audits_for_session_owner(&mut self, session_id: Option<&str>) -> bool { - let accepts_without_target = self.accepts_unmaterialized_page_command(session_id, None); + let accepts_without_target = + self.accepts_unmaterialized_page_command_for_session(session_id); self.with_target_session_owner_mut(session_id, |owner| owner.disable_audits()) .unwrap_or(accepts_without_target) } @@ -496,15 +498,12 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> Option { - self.page_domain_enabled_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.page_domain_enabled_for_owner(&owner) } - pub(crate) fn page_domain_enabled_for_route( - &self, - session_id: Option<&str>, - owner_route: Option<&crate::conn::CdpSessionRoute>, - ) -> Option { - self.target_session_owner_ref_for_route(session_id, owner_route) + pub(crate) fn page_domain_enabled_for_owner(&self, owner: &CommandOwnerScope) -> Option { + self.target_session_owner_ref_for_owner(owner) .and_then(|owner| owner.devtools_session_state()) .map(devtools_session_page_domain_enabled) } @@ -536,10 +535,9 @@ impl CdpConnection { }) } - pub(crate) fn record_main_document_resource_body_for_route( + pub(crate) fn record_main_document_resource_body_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&crate::conn::CdpSessionRoute>, + owner: &CommandOwnerScope, frame_id: String, loader_id: String, url: url::Url, @@ -547,7 +545,7 @@ impl CdpConnection { from_cache: bool, body: crate::conn::CapturedBody, ) -> bool { - self.with_target_owner_state_for_route_mut(session_id, owner_route, |owner_state| { + self.with_target_owner_state_for_owner_mut(owner, |owner_state| { owner_state.page_resource_store.record_main_document_body( frame_id, loader_id, @@ -571,27 +569,23 @@ impl CdpConnection { body: Option, ) -> bool { if self - .runtime_session_owner_slot_for_route(owner.session_id(), owner.session_owner_route()) + .runtime_session_owner_slot_for_owner(owner) .ok() .and_then(TargetRuntimeSlot::committed_document_loader_id) != Some(loader_id.as_str()) { return false; } - self.with_target_owner_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |owner_state| { - owner_state.page_resource_store.commit_main_document( - frame_id, - loader_id, - url, - response_headers, - from_cache, - body, - ); - }, - ) + self.with_target_owner_state_for_owner_mut(owner, |owner_state| { + owner_state.page_resource_store.commit_main_document( + frame_id, + loader_id, + url, + response_headers, + from_cache, + body, + ); + }) .is_some() } @@ -623,15 +617,11 @@ impl CdpConnection { owner: &CommandOwnerScope, loader_id: &str, ) { - let _ = self.with_target_owner_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |owner_state| { - owner_state - .page_resource_store - .discard_uncommitted_loader(loader_id); - }, - ); + let _ = self.with_target_owner_state_for_owner_mut(owner, |owner_state| { + owner_state + .page_resource_store + .discard_uncommitted_loader(loader_id); + }); } pub(crate) fn set_page_domain_enabled_for_session_owner( @@ -650,7 +640,7 @@ impl CdpConnection { .with_target_session_owner_mut(session_id, |owner| { owner.set_page_domain_enabled(enabled, subscription_generation) }) - .unwrap_or_else(|| self.accepts_unmaterialized_page_command(session_id, None)); + .unwrap_or_else(|| self.accepts_unmaterialized_page_command_for_session(session_id)); if handled && let Some(browser_context_id) = owner_browser_context_id.as_deref() { self.sync_javascript_dialog_handler_enabled_for_browser_context(browser_context_id); } @@ -682,33 +672,23 @@ impl CdpConnection { owner: &crate::conn::CommandOwnerScope, enabled: bool, ) -> bool { - let accepts_without_target = self - .accepts_unmaterialized_page_command(owner.session_id(), owner.session_owner_route()); + let accepts_without_target = self.accepts_unmaterialized_page_command(owner); let handled = self - .with_target_session_owner_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - |owner| owner.set_console_enabled(enabled), - ) + .with_target_session_owner_mut_for_owner(owner, |owner| { + owner.set_console_enabled(enabled) + }) .unwrap_or(accepts_without_target); if handled { let renderer_console_agent_owns_page_console_api_events = enabled && self - .runtime_session_owner_slot_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + .runtime_session_owner_slot_for_owner(owner) .is_ok_and(|slot| slot.has_loaded_page()); - let _ = self.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |state| { - state - .console_output_session_state - .renderer_console_agent_owns_page_console_api_events = - renderer_console_agent_owns_page_console_api_events; - }, - ); + let _ = self.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state + .console_output_session_state + .renderer_console_agent_owns_page_console_api_events = + renderer_console_agent_owns_page_console_api_events; + }); } handled } @@ -725,21 +705,17 @@ impl CdpConnection { &mut self, owner: &crate::conn::CommandOwnerScope, ) -> bool { - let accepts_without_target = self - .accepts_unmaterialized_page_command(owner.session_id(), owner.session_owner_route()); - self.with_target_session_owner_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - |owner| owner.clear_console_messages(), - ) - .unwrap_or(accepts_without_target) + let accepts_without_target = self.accepts_unmaterialized_page_command(owner); + self.with_target_session_owner_mut_for_owner(owner, |owner| owner.clear_console_messages()) + .unwrap_or(accepts_without_target) } pub(crate) fn enable_log_for_session_owner( &mut self, session_id: Option<&str>, ) -> SessionOwnerLogEnableResult { - let accepts_without_target = self.accepts_unmaterialized_page_command(session_id, None); + let accepts_without_target = + self.accepts_unmaterialized_page_command_for_session(session_id); self.with_target_session_owner_mut(session_id, |owner| owner.enable_log()) .unwrap_or({ if accepts_without_target { @@ -751,13 +727,15 @@ impl CdpConnection { } pub(crate) fn disable_log_for_session_owner(&mut self, session_id: Option<&str>) -> bool { - let accepts_without_target = self.accepts_unmaterialized_page_command(session_id, None); + let accepts_without_target = + self.accepts_unmaterialized_page_command_for_session(session_id); self.with_target_session_owner_mut(session_id, |owner| owner.disable_log()) .unwrap_or(accepts_without_target) } pub(crate) fn clear_log_for_session_owner(&mut self, session_id: Option<&str>) -> bool { - let accepts_without_target = self.accepts_unmaterialized_page_command(session_id, None); + let accepts_without_target = + self.accepts_unmaterialized_page_command_for_session(session_id); self.with_target_session_owner_mut(session_id, |owner| owner.clear_log()) .unwrap_or(accepts_without_target) } @@ -786,18 +764,17 @@ impl CdpConnection { session_id: Option<&str>, enabled: bool, ) -> bool { - self.set_page_file_chooser_opened_event_enabled_for_route(session_id, None, enabled) + let owner = CommandOwnerScope::capture(self, session_id); + self.set_page_file_chooser_opened_event_enabled_for_owner(&owner, enabled) } - fn set_page_file_chooser_opened_event_enabled_for_route( + fn set_page_file_chooser_opened_event_enabled_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, enabled: bool, ) -> bool { - let accepts_without_target = - self.accepts_unmaterialized_page_command(session_id, owner_route); - self.with_target_session_owner_mut_for_route(session_id, owner_route, |owner| { + let accepts_without_target = self.accepts_unmaterialized_page_command(owner); + self.with_target_session_owner_mut_for_owner(owner, |owner| { owner.set_page_file_chooser_opened_event_enabled(enabled) }) .unwrap_or(accepts_without_target) @@ -812,7 +789,7 @@ impl CdpConnection { .map(|(browser_context_id, _)| browser_context_id); let handled = self .with_target_session_owner_mut(session_id, |owner| owner.disable_page_domain()) - .unwrap_or_else(|| self.accepts_unmaterialized_page_command(session_id, None)); + .unwrap_or_else(|| self.accepts_unmaterialized_page_command_for_session(session_id)); if handled && let Some(browser_context_id) = owner_browser_context_id.as_deref() { self.sync_javascript_dialog_handler_enabled_for_browser_context(browser_context_id); } @@ -823,14 +800,20 @@ impl CdpConnection { let Some(route) = self.target_session_route_for_target_id(target_id) else { return false; }; - self.set_page_file_chooser_opened_event_enabled_for_route(None, Some(&route), true) + self.set_page_file_chooser_opened_event_enabled_for_owner( + &CommandOwnerScope::for_route(route), + true, + ) } pub fn disable_file_dialog_opened_listener_for_target(&mut self, target_id: &str) -> bool { let Some(route) = self.target_session_route_for_target_id(target_id) else { return false; }; - self.set_page_file_chooser_opened_event_enabled_for_route(None, Some(&route), false) + self.set_page_file_chooser_opened_event_enabled_for_owner( + &CommandOwnerScope::for_route(route), + false, + ) } pub(crate) fn set_page_lifecycle_events_enabled_for_session_owner( @@ -838,7 +821,8 @@ impl CdpConnection { session_id: Option<&str>, enabled: bool, ) -> PageLifecycleEventsEnableResult { - let accepts_without_target = self.accepts_unmaterialized_page_command(session_id, None); + let accepts_without_target = + self.accepts_unmaterialized_page_command_for_session(session_id); self.with_target_session_owner_mut(session_id, |owner| { owner.set_page_lifecycle_events_enabled(enabled) }) @@ -858,7 +842,8 @@ impl CdpConnection { session_id: Option<&str>, enabled: bool, ) -> bool { - let accepts_without_target = self.accepts_unmaterialized_page_command(session_id, None); + let accepts_without_target = + self.accepts_unmaterialized_page_command_for_session(session_id); self.with_target_session_owner_mut(session_id, |owner| { owner.set_page_bypass_csp_enabled(enabled) }) @@ -870,7 +855,8 @@ impl CdpConnection { session_id: Option<&str>, font_families: serde_json::Map, ) -> bool { - let accepts_without_target = self.accepts_unmaterialized_page_command(session_id, None); + let accepts_without_target = + self.accepts_unmaterialized_page_command_for_session(session_id); self.with_target_session_owner_mut(session_id, |owner| { owner.set_page_font_families(font_families) }) @@ -882,7 +868,8 @@ impl CdpConnection { session_id: Option<&str>, enabled: bool, ) -> bool { - let accepts_without_target = self.accepts_unmaterialized_page_command(session_id, None); + let accepts_without_target = + self.accepts_unmaterialized_page_command_for_session(session_id); self.with_target_session_owner_mut(session_id, |owner| { owner.set_page_intercept_file_chooser_dialog_enabled(enabled) }) @@ -915,27 +902,25 @@ impl CdpConnection { .unwrap_or(false) } - pub(crate) fn begin_page_screencast_capture_for_route( + pub(crate) fn begin_page_screencast_capture_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, generation: i32, ) -> Option { Some( - self.target_session_owner_mut_for_route(session_id, owner_route)? + self.target_session_owner_mut_for_owner(owner)? .begin_page_screencast_capture(generation), ) } - pub(crate) fn complete_page_screencast_capture_for_route( + pub(crate) fn complete_page_screencast_capture_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, generation: i32, frame_emitted: bool, ) -> Option { Some( - self.target_session_owner_mut_for_route(session_id, owner_route)? + self.target_session_owner_mut_for_owner(owner)? .complete_page_screencast_capture(generation, frame_emitted), ) } @@ -961,7 +946,8 @@ impl CdpConnection { session_id: Option<&str>, time_domain: PerformanceTimeDomain, ) -> Option { - let accepts_without_target = self.accepts_unmaterialized_page_command(session_id, None); + let accepts_without_target = + self.accepts_unmaterialized_page_command_for_session(session_id); self.with_target_session_owner_mut(session_id, |owner| { owner.enable_performance(time_domain) }) @@ -972,7 +958,8 @@ impl CdpConnection { &mut self, session_id: Option<&str>, ) -> bool { - let accepts_without_target = self.accepts_unmaterialized_page_command(session_id, None); + let accepts_without_target = + self.accepts_unmaterialized_page_command_for_session(session_id); self.with_target_session_owner_mut(session_id, |owner| owner.disable_performance()) .unwrap_or(accepts_without_target) } @@ -982,7 +969,8 @@ impl CdpConnection { session_id: Option<&str>, time_domain: PerformanceTimeDomain, ) -> Option { - let accepts_without_target = self.accepts_unmaterialized_page_command(session_id, None); + let accepts_without_target = + self.accepts_unmaterialized_page_command_for_session(session_id); self.with_target_session_owner_mut(session_id, |owner| { owner.set_performance_time_domain(time_domain) }) diff --git a/moli-protocol/src/conn/browser_context/runtime_owner.rs b/moli-protocol/src/conn/browser_context/runtime_owner.rs index 2aac07b060..3aeb63e238 100644 --- a/moli-protocol/src/conn/browser_context/runtime_owner.rs +++ b/moli-protocol/src/conn/browser_context/runtime_owner.rs @@ -56,7 +56,8 @@ impl CdpConnection { session_id: Option<&str>, enabled: bool, ) -> SessionOwnerInspectorEnableResult { - let accepts_without_target = self.accepts_unmaterialized_page_command(session_id, None); + let accepts_without_target = + self.accepts_unmaterialized_page_command_for_session(session_id); let target_crashed = self .target_owner_state_for_session(session_id) .is_some_and(|owner_state| owner_state.target_crash_state.is_crashed()); @@ -90,14 +91,11 @@ impl CdpConnection { owner: &crate::conn::CommandOwnerScope, enabled: bool, ) -> SessionOwnerRuntimeFrontendEnableResult { - let accepts_without_target = self - .accepts_unmaterialized_page_command(owner.session_id(), owner.session_owner_route()); + let accepts_without_target = self.accepts_unmaterialized_page_command(owner); let result = self - .with_target_session_owner_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - |owner| owner.set_runtime_frontend_enabled(enabled), - ) + .with_target_session_owner_mut_for_owner(owner, |owner| { + owner.set_runtime_frontend_enabled(enabled) + }) .unwrap_or({ if accepts_without_target { SessionOwnerRuntimeFrontendEnableResult::Handled @@ -108,11 +106,9 @@ impl CdpConnection { if matches!(result, SessionOwnerRuntimeFrontendEnableResult::Handled) && !enabled { let _ = self .set_renderer_runtime_agent_owns_page_console_api_events_for_owner(owner, false); - let _ = self.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |state| state.clear_child_default_context_emission_state(), - ); + let _ = self.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.clear_child_default_context_emission_state() + }); } result } @@ -134,27 +130,22 @@ impl CdpConnection { } let owns = owns && self - .runtime_session_owner_slot_for_route(session_id, owner.session_owner_route()) + .runtime_session_owner_slot_for_owner(owner) .is_ok_and(|slot| slot.has_loaded_page()); - self.with_target_devtools_session_state_for_route_mut( - session_id, - owner.session_owner_route(), - |state| { - state - .console_output_session_state - .renderer_runtime_agent_owns_page_console_api_events = owns; - }, - ) + self.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state + .console_output_session_state + .renderer_runtime_agent_owns_page_console_api_events = owns; + }) .is_some() } - pub(crate) fn merge_v8_inspector_session_state_for_route( + pub(crate) fn merge_v8_inspector_session_state_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &crate::conn::CommandOwnerScope, state: V8InspectorSessionState, ) -> bool { - self.with_target_devtools_session_state_for_route_mut(session_id, owner_route, |session| { + self.with_target_devtools_session_state_for_owner_mut(owner, |session| { session.inspector_session_state.v8_state = Some(state); }) .is_some() diff --git a/moli-protocol/src/conn/browser_context/session_owner.rs b/moli-protocol/src/conn/browser_context/session_owner.rs index a113c24587..d7973dc54d 100644 --- a/moli-protocol/src/conn/browser_context/session_owner.rs +++ b/moli-protocol/src/conn/browser_context/session_owner.rs @@ -1,6 +1,4 @@ -#[cfg(test)] -use crate::conn::BrowserContext; -use crate::conn::{CdpConnection, CdpSessionRoute, PageTargetHost}; +use crate::conn::{CdpConnection, CdpSessionRoute, CommandOwnerScope, PageTargetHost}; use moli_page_types::DevToolsSessionKey; pub(super) struct TargetSessionOwner { @@ -13,34 +11,23 @@ impl CdpConnection { /// Some generated Page-domain agents acknowledge enable/disable commands /// before a Page host exists. Keep that protocol behavior at the command /// boundary instead of manufacturing an owner that does not own a Page. - pub(super) fn accepts_unmaterialized_page_command( - &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, - ) -> bool { - if session_id.is_some() { + pub(super) fn accepts_unmaterialized_page_command(&self, owner: &CommandOwnerScope) -> bool { + if owner.session_id().is_some() { return false; } - match owner_route { + match owner.explicit_route() { Some(CdpSessionRoute::Browser | CdpSessionRoute::BrowserContext { .. }) => true, Some(_) => false, - None => self - .browser_context - .as_ref() - .and_then(|browser_context| browser_context.active_target_id()) - .is_none(), + None => false, } } - #[cfg(test)] - pub(crate) fn with_background_target_session( - &mut self, + pub(super) fn accepts_unmaterialized_page_command_for_session( + &self, session_id: Option<&str>, - f: impl FnOnce(&mut BrowserContext, &str) -> R, - ) -> Option { - let (browser_context_id, target_id) = self.background_target_route(session_id)?; - let browser_context = self.browser_context_by_id_mut(&browser_context_id)?; - Some(f(browser_context, &target_id)) + ) -> bool { + let owner = CommandOwnerScope::capture(self, session_id); + self.accepts_unmaterialized_page_command(&owner) } pub(crate) fn mutate_target_page_state_for_session( @@ -57,32 +44,16 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> Option { - self.target_session_owner_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.target_session_owner_for_owner(&owner) } - /// Resolves target ownership from an explicit command route. A concrete - /// session always resolves through the session registry; `owner_route` - /// selects the owner of an internal command without a CDP session. - pub(super) fn target_session_owner_for_route( + /// Resolves target ownership from the command's single authority. + pub(super) fn target_session_owner_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - let route = match session_id { - Some(session_id) => self.session_route(Some(session_id))?, - None => match owner_route { - Some(route) => route.clone(), - None => { - let browser_context = self.browser_context.as_ref()?; - let target_id = browser_context.active_target_id()?; - return Some(TargetSessionOwner { - browser_context_id: browser_context.id.clone(), - target_id: target_id.to_owned(), - session_key: DevToolsSessionKey::Primary, - }); - } - }, - }; + let route = owner.resolve_route(self)?; match route { CdpSessionRoute::Browser => { @@ -128,6 +99,7 @@ impl CdpConnection { #[cfg(test)] mod tests { use super::*; + use crate::conn::BrowserContext; #[test] fn empty_browser_context_does_not_materialize_a_page_owner() { @@ -135,8 +107,12 @@ mod tests { conn.browser_context = Some(BrowserContext::new("BID-empty-owner".to_owned())); assert!(conn.target_session_owner(None).is_none()); - assert!(conn.accepts_unmaterialized_page_command(None, None)); - assert!(!conn.accepts_unmaterialized_page_command(Some("SID-missing"), None)); + assert!(conn.accepts_unmaterialized_page_command(&CommandOwnerScope::capture(&conn, None))); + assert!( + !conn.accepts_unmaterialized_page_command(&CommandOwnerScope::for_session( + "SID-missing" + )) + ); } #[test] @@ -152,10 +128,8 @@ mod tests { session_key: DevToolsSessionKey::Primary, }; - assert!( - conn.target_session_owner_for_route(None, Some(&stale_route)) - .is_none() - ); - assert!(!conn.accepts_unmaterialized_page_command(None, Some(&stale_route))); + let owner = CommandOwnerScope::for_route(stale_route); + assert!(conn.target_session_owner_for_owner(&owner).is_none()); + assert!(!conn.accepts_unmaterialized_page_command(&owner)); } } diff --git a/moli-protocol/src/conn/browser_context/target_session_owner.rs b/moli-protocol/src/conn/browser_context/target_session_owner.rs index cb28a58c0d..7c229885b7 100644 --- a/moli-protocol/src/conn/browser_context/target_session_owner.rs +++ b/moli-protocol/src/conn/browser_context/target_session_owner.rs @@ -1122,15 +1122,15 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> TargetNavigationLoadInputs { - self.navigation_load_inputs_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.navigation_load_inputs_for_owner(&owner) } - pub(crate) fn navigation_load_inputs_for_route( + pub(crate) fn navigation_load_inputs_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> TargetNavigationLoadInputs { - let mut inputs = match self.target_session_owner_ref_for_route(session_id, owner_route) { + let mut inputs = match self.target_session_owner_ref_for_owner(owner) { None => self .browser_context .as_ref() @@ -1152,19 +1152,17 @@ impl CdpConnection { inputs } - pub(crate) fn navigation_initiator_url_for_route( + pub(crate) fn navigation_initiator_url_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - self.target_session_owner_ref_for_route(session_id, owner_route) + self.target_session_owner_ref_for_owner(owner) .and_then(|owner| owner.navigation_initiator_url()) } - pub(crate) fn prepare_navigation_request_for_route( + pub(crate) fn prepare_navigation_request_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, requested_url: &Url, referrer: Option<&str>, is_data_url: bool, @@ -1176,9 +1174,9 @@ impl CdpConnection { let mut network_request_id_allocator = std::mem::take(&mut self.network_request_id_allocator); let result = self - .target_session_owner_mut_for_route(session_id, owner_route) - .and_then(|mut owner| { - owner.prepare_navigation_request( + .target_session_owner_mut_for_owner(owner) + .and_then(|mut resolved| { + resolved.prepare_navigation_request( requested_url, referrer, is_data_url, @@ -1190,13 +1188,12 @@ impl CdpConnection { result } - pub(crate) fn register_pending_fetch_navigation_request_for_route( + pub(crate) fn register_pending_fetch_navigation_request_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, pending: PendingFetchNavigation, ) -> Option<()> { - self.target_session_owner_mut_for_route(session_id, owner_route)? + self.target_session_owner_mut_for_owner(owner)? .register_pending_fetch_navigation_request(pending) } @@ -1204,7 +1201,7 @@ impl CdpConnection { &mut self, owner: &crate::conn::CommandOwnerScope, ) -> Option { - self.target_session_owner_mut_for_route(owner.session_id(), owner.session_owner_route())? + self.target_session_owner_mut_for_owner(owner)? .prepare_loaded_navigation_commit() } @@ -1214,7 +1211,7 @@ impl CdpConnection { main_document_commit: &RendererMainDocumentCommit, target_url: &Url, ) -> Option<()> { - self.target_session_owner_mut_for_route(owner.session_id(), owner.session_owner_route())? + self.target_session_owner_mut_for_owner(owner)? .commit_loaded_navigation_target_identity(main_document_commit, target_url) } @@ -1225,18 +1222,16 @@ impl CdpConnection { renderer_attachment_commit: LoadedNavigationRendererAttachmentCommit, history_url: &Url, ) -> Option> { - self.target_session_owner_mut_for_route(owner.session_id(), owner.session_owner_route())? + self.target_session_owner_mut_for_owner(owner)? .commit_loaded_navigation_page_async(page, renderer_attachment_commit, history_url) .await } - pub(crate) fn initial_document_page_owner_for_route( + pub(crate) fn initial_document_page_owner_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - let (browser_context_id, target_id) = - self.target_owner_identity_for_route(session_id, owner_route)?; + let (browser_context_id, target_id) = self.target_owner_identity_for_owner(owner)?; Some(InitialDocumentPageOwner { browser_context_id, target_id: target_id?, @@ -1299,16 +1294,15 @@ impl CdpConnection { &mut self, owner: &CommandOwnerScope, ) -> Option<()> { - self.target_session_owner_mut_for_route(owner.session_id(), owner.session_owner_route())? + self.target_session_owner_mut_for_owner(owner)? .clear_pending_navigation_history_update() } - pub(crate) async fn mark_target_crashed_for_route_async( + pub(crate) async fn mark_target_crashed_for_owner_async( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option<()> { - self.target_session_owner_mut_for_route(session_id, owner_route)? + self.target_session_owner_mut_for_owner(owner)? .mark_target_crashed_async() .await } @@ -1318,7 +1312,7 @@ impl CdpConnection { owner: &CommandOwnerScope, final_url: &Url, ) -> Option<()> { - self.target_session_owner_mut_for_route(owner.session_id(), owner.session_owner_route())? + self.target_session_owner_mut_for_owner(owner)? .discard_loaded_page_after_failed_navigation_async(final_url) .await } @@ -1330,14 +1324,15 @@ impl CdpConnection { reason: &'static str, ) -> Option { let primary_route = self.target_session_route_for_target_id(target_id)?; + let primary_owner = CommandOwnerScope::for_route(primary_route); let session_owners = self - .page_event_session_ids_for_route(None, Some(&primary_route)) + .page_event_session_ids_for_owner(&primary_owner) .into_iter() .map(|session_id| { session_id .as_deref() .map(CommandOwnerScope::for_session) - .unwrap_or_else(|| CommandOwnerScope::for_route(primary_route.clone())) + .unwrap_or_else(|| primary_owner.clone()) }) .collect::>(); let mut claimed_await_events = Vec::new(); @@ -1476,20 +1471,12 @@ impl CdpConnection { } } - pub(crate) fn target_session_owner_aggregate_fetch_config( + pub(crate) fn target_session_owner_aggregate_fetch_config_for_owner( &self, - session_id: Option<&str>, - ) -> Option { - self.target_session_owner_aggregate_fetch_config_for_route(session_id, None) - } - - pub(crate) fn target_session_owner_aggregate_fetch_config_for_route( - &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { Some( - self.target_session_owner_ref_for_route(session_id, owner_route)? + self.target_session_owner_ref_for_owner(owner)? .aggregate_fetch_config(), ) } @@ -1502,12 +1489,11 @@ impl CdpConnection { .page_session_state() } - pub(crate) fn target_page_session_state_for_route( + pub(crate) fn target_page_session_state_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option<&TargetPageSessionState> { - self.target_session_owner_ref_for_route(session_id, owner_route)? + self.target_session_owner_ref_for_owner(owner)? .page_session_state() } @@ -1515,15 +1501,15 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> Option<&DevToolsSessionState> { - self.target_devtools_session_state_for_route(session_id, None) + self.target_session_owner_ref(session_id)? + .devtools_session_state() } - pub(crate) fn target_devtools_session_state_for_route( + pub(crate) fn target_devtools_session_state_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option<&DevToolsSessionState> { - self.target_session_owner_ref_for_route(session_id, owner_route)? + self.target_session_owner_ref_for_owner(owner)? .devtools_session_state() } @@ -1535,31 +1521,28 @@ impl CdpConnection { .runtime_session_state() } - pub(crate) fn target_runtime_session_state_for_route( + pub(crate) fn target_runtime_session_state_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option<&TargetRuntimeSessionState> { - self.target_session_owner_ref_for_route(session_id, owner_route)? + self.target_session_owner_ref_for_owner(owner)? .runtime_session_state() } - pub(crate) fn target_runtime_bindings_for_renderer_route( + pub(crate) fn target_runtime_bindings_for_renderer_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Vec { - self.target_session_owner_ref_for_route(session_id, owner_route) + self.target_session_owner_ref_for_owner(owner) .map(|owner| owner.runtime_bindings_for_renderer()) .unwrap_or_default() } - pub(crate) fn target_runtime_bindings_for_current_inspector_route( + pub(crate) fn target_runtime_bindings_for_current_inspector_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Vec { - self.target_session_owner_ref_for_route(session_id, owner_route) + self.target_session_owner_ref_for_owner(owner) .and_then(|owner| owner.devtools_session_state()) .map(|state| state.runtime_bindings.clone()) .unwrap_or_default() @@ -1569,61 +1552,61 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> Option { - self.target_renderer_runtime_inspector_session_id_for_route(session_id, None) + self.target_session_owner_ref(session_id) + .and_then(|owner| owner.renderer_runtime_inspector_session_id()) } - pub(crate) fn target_renderer_runtime_inspector_session_id_for_route( + pub(crate) fn target_renderer_runtime_inspector_session_id_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - self.target_session_owner_ref_for_route(session_id, owner_route) + self.target_session_owner_ref_for_owner(owner) .and_then(|owner| owner.renderer_runtime_inspector_session_id()) } pub(crate) fn target_owner_state_for_session( &self, session_id: Option<&str>, - ) -> Option<&TargetOwnerState> { - self.target_owner_state_for_route(session_id, None) - } - - pub(crate) fn target_owner_state_for_route( - &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, ) -> Option<&TargetOwnerState> { Some( - self.target_session_owner_ref_for_route(session_id, owner_route)? + self.target_session_owner_ref(session_id)? .target_owner_state(), ) } - pub(crate) fn target_owner_has_bidi_channel_preload_script_for_route( + pub(crate) fn target_owner_state_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, + ) -> Option<&TargetOwnerState> { + Some( + self.target_session_owner_ref_for_owner(owner)? + .target_owner_state(), + ) + } + + pub(crate) fn target_owner_has_bidi_channel_preload_script_for_owner( + &self, + owner: &CommandOwnerScope, ) -> bool { let target_owner_has_script = self - .target_owner_state_for_route(session_id, owner_route) + .target_owner_state_for_owner(owner) .is_some_and(TargetOwnerState::has_bidi_channel_preload_script); if target_owner_has_script { return true; } - self.target_owner_identity_for_route(session_id, owner_route) + self.target_owner_identity_for_owner(owner) .and_then(|(browser_context_id, _)| self.browser_context_by_id(&browser_context_id)) .is_some_and(|browser_context| { browser_context.has_default_bidi_channel_preload_script() }) } - pub(crate) fn target_owner_bidi_channel_preload_handoffs_for_route( + pub(crate) fn target_owner_bidi_channel_preload_handoffs_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Vec { let mut handoffs = Vec::new(); - if let Some(owner_state) = self.target_owner_state_for_route(session_id, owner_route) { + if let Some(owner_state) = self.target_owner_state_for_owner(owner) { handoffs.extend( owner_state .document_start_scripts @@ -1632,7 +1615,7 @@ impl CdpConnection { ); } if let Some(browser_context) = self - .target_owner_identity_for_route(session_id, owner_route) + .target_owner_identity_for_owner(owner) .and_then(|(browser_context_id, _)| self.browser_context_by_id(&browser_context_id)) { handoffs.extend( @@ -1650,17 +1633,17 @@ impl CdpConnection { session_id: Option<&str>, f: impl FnOnce(&mut TargetOwnerState) -> R, ) -> Option { - self.with_target_owner_state_for_route_mut(session_id, None, f) + let owner = CommandOwnerScope::capture(self, session_id); + self.with_target_owner_state_for_owner_mut(&owner, f) } - pub(crate) fn with_target_owner_state_for_route_mut( + pub(crate) fn with_target_owner_state_for_owner_mut( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, f: impl FnOnce(&mut TargetOwnerState) -> R, ) -> Option { Some( - self.target_session_owner_mut_for_route(session_id, owner_route)? + self.target_session_owner_mut_for_owner(owner)? .mutate_target_owner_state(f), ) } @@ -1674,13 +1657,12 @@ impl CdpConnection { .mutate_session_state(|mut state| Some(f(state.devtools_session_state_mut()))) } - pub(crate) fn with_target_devtools_session_state_for_route_mut( + pub(crate) fn with_target_devtools_session_state_for_owner_mut( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, f: impl FnOnce(&mut DevToolsSessionState) -> R, ) -> Option { - self.target_session_owner_mut_for_route(session_id, owner_route)? + self.target_session_owner_mut_for_owner(owner)? .mutate_session_state(|mut state| Some(f(state.devtools_session_state_mut()))) } @@ -1691,20 +1673,20 @@ impl CdpConnection { Some(self.target_session_owner_ref(session_id)?.owner_identity()) } - pub(crate) fn target_owner_identity_for_route( + pub(crate) fn target_owner_identity_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option<(String, Option)> { - if session_id.is_none() - && let Some(CdpSessionRoute::BrowserContext { browser_context_id }) = owner_route + if owner.session_id().is_none() + && let Some(CdpSessionRoute::BrowserContext { browser_context_id }) = + owner.explicit_route() { return self .browser_context_by_id(browser_context_id) .map(|_| (browser_context_id.clone(), None)); } Some( - self.target_session_owner_ref_for_route(session_id, owner_route)? + self.target_session_owner_ref_for_owner(owner)? .owner_identity(), ) } @@ -1720,16 +1702,15 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> Option { - self.target_page_residence_identity_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.target_page_residence_identity_for_owner(&owner) } - pub(crate) fn target_page_residence_identity_for_route( + pub(crate) fn target_page_residence_identity_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - let (browser_context_id, routed_target_id) = - self.target_owner_identity_for_route(session_id, owner_route)?; + let (browser_context_id, routed_target_id) = self.target_owner_identity_for_owner(owner)?; // Context-scoped work may not carry a Page id. Freeze its concrete // active target before an async boundary so later foreground changes // cannot redirect output from the old Page. @@ -1739,7 +1720,7 @@ impl CdpConnection { .map(str::to_owned) }); let page_attachment_id = self - .runtime_session_owner_slot_for_route(session_id, owner_route) + .runtime_session_owner_slot_for_owner(owner) .ok()? .page_attachment_id()?; Some(TargetPageResidenceIdentity::new( @@ -1756,20 +1737,18 @@ impl CdpConnection { /// before protocol commits that Page into the target slot. The reservation /// therefore owns an explicit attachment id before renderer work starts; /// callers never predict that identity from mutable current-Page state. - pub(crate) fn pending_target_page_residence_identity_for_route( + pub(crate) fn pending_target_page_residence_identity_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - let (browser_context_id, routed_target_id) = - self.target_owner_identity_for_route(session_id, owner_route)?; + let (browser_context_id, routed_target_id) = self.target_owner_identity_for_owner(owner)?; let target_id = routed_target_id.or_else(|| { self.browser_context_by_id(&browser_context_id) .and_then(|browser_context| browser_context.active_target_id()) .map(str::to_owned) }); let page_attachment_id = self - .runtime_session_owner_slot_for_route(session_id, owner_route) + .runtime_session_owner_slot_for_owner(owner) .ok()? .pending_page_attachment_id()?; Some(TargetPageResidenceIdentity::new( @@ -1779,21 +1758,19 @@ impl CdpConnection { )) } - pub(crate) fn reserve_target_page_residence_identity_for_route( + pub(crate) fn reserve_target_page_residence_identity_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, renderer_page: crate::conn::RendererPageResidenceIdentity, ) -> Option { - let (browser_context_id, routed_target_id) = - self.target_owner_identity_for_route(session_id, owner_route)?; + let (browser_context_id, routed_target_id) = self.target_owner_identity_for_owner(owner)?; let target_id = routed_target_id.or_else(|| { self.browser_context_by_id(&browser_context_id) .and_then(|browser_context| browser_context.active_target_id()) .map(str::to_owned) }); let page_attachment_id = self - .runtime_session_owner_slot_mut_for_route(session_id, owner_route) + .runtime_session_owner_slot_mut_for_owner(owner) .ok()? .reserve_renderer_page_attachment(renderer_page); Some(TargetPageResidenceIdentity::new( @@ -1805,9 +1782,8 @@ impl CdpConnection { /// Checks that deferred Page-owned work still addresses the same target /// Page-slot residence from which it was captured. - pub(crate) fn target_page_residence_identity_is_current_for_session( + pub(crate) fn target_page_residence_identity_is_current( &self, - _session_id: Option<&str>, expected: &TargetPageResidenceIdentity, ) -> bool { self.browser_context_by_id(expected.browser_context_id()) @@ -1816,12 +1792,11 @@ impl CdpConnection { }) } - pub(crate) fn capture_target_page_residence_token_for_route( + pub(crate) fn capture_target_page_residence_token_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - self.runtime_session_owner_slot_mut_for_route(session_id, owner_route) + self.runtime_session_owner_slot_mut_for_owner(owner) .ok()? .page_slot_mut() .page_residence_token() @@ -1832,17 +1807,17 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> Option { - self.target_page_protocol_attachment_identity_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.target_page_protocol_attachment_identity_for_owner(&owner) } - pub(crate) fn target_page_protocol_attachment_identity_for_route( + pub(crate) fn target_page_protocol_attachment_identity_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { Some(crate::conn::TargetPageProtocolAttachmentIdentity::new( - self.target_page_residence_identity_for_route(session_id, owner_route)?, - session_id.map(str::to_owned), + self.target_page_residence_identity_for_owner(owner)?, + owner.session_id().map(str::to_owned), )) } @@ -1856,15 +1831,15 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> Option { - self.renderer_page_residence_identity_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.renderer_page_residence_identity_for_owner(&owner) } - pub(crate) fn renderer_page_residence_identity_for_route( + pub(crate) fn renderer_page_residence_identity_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - self.runtime_session_owner_slot_for_route(session_id, owner_route) + self.runtime_session_owner_slot_for_owner(owner) .ok()? .loaded_page() .map(crate::conn::RendererPageResidenceIdentity::from_page) @@ -1885,32 +1860,19 @@ impl CdpConnection { source_owner: &crate::conn::CommandOwnerScope, renderer_inspector_session_id: Option<&str>, ) -> Option { - let source = self.target_page_protocol_attachment_identity_for_route( - source_owner.session_id(), - source_owner.session_owner_route(), - )?; + let source = self.target_page_protocol_attachment_identity_for_owner(source_owner)?; let protocol_session_id = renderer_inspector_session_id .map(str::to_owned) - .or_else(|| { - self.runtime_session_owner_primary_session_id_for_route( - source_owner.session_id(), - source_owner.session_owner_route(), - ) - }); - let protocol_owner_route = protocol_session_id - .is_none() - .then(|| source_owner.session_owner_route()) - .flatten(); - let attachment = self.target_page_protocol_attachment_identity_for_route( - protocol_session_id.as_deref(), - protocol_owner_route, - )?; + .or_else(|| self.runtime_session_owner_primary_session_id_for_owner(source_owner)); + let protocol_owner = protocol_session_id + .as_deref() + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| source_owner.clone()); + let attachment = + self.target_page_protocol_attachment_identity_for_owner(&protocol_owner)?; if attachment.page_owner() != source.page_owner() || self - .target_renderer_runtime_inspector_session_id_for_route( - protocol_session_id.as_deref(), - protocol_owner_route, - ) + .target_renderer_runtime_inspector_session_id_for_owner(&protocol_owner) .as_deref() != renderer_inspector_session_id { @@ -1931,7 +1893,7 @@ impl CdpConnection { .as_ref() == Some(expected); } - self.target_page_residence_identity_is_current_for_session(None, expected.page_owner()) + self.target_page_residence_identity_is_current(expected.page_owner()) } /// Binds renderer-produced child-frame activity to the Page attachment @@ -1942,21 +1904,17 @@ impl CdpConnection { session_id: Option<&str>, root_document: moli_core::RendererDocumentLifecycleIdentity, ) -> Option { - self.target_root_document_protocol_attachment_identity_for_route( - session_id, - None, - root_document, - ) + let owner = CommandOwnerScope::capture(self, session_id); + self.target_root_document_protocol_attachment_identity_for_owner(&owner, root_document) } - pub(crate) fn target_root_document_protocol_attachment_identity_for_route( + pub(crate) fn target_root_document_protocol_attachment_identity_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, root_document: moli_core::RendererDocumentLifecycleIdentity, ) -> Option { let binding = crate::conn::TargetRootDocumentProtocolAttachmentIdentity::new( - self.target_page_protocol_attachment_identity_for_route(session_id, owner_route)?, + self.target_page_protocol_attachment_identity_for_owner(owner)?, root_document, ); self.target_root_document_protocol_attachment_identity_is_current(&binding) @@ -1979,12 +1937,11 @@ impl CdpConnection { == Some(expected.root_document()) } - pub(crate) fn target_root_document_lifecycle_identity_for_route( + pub(crate) fn target_root_document_lifecycle_identity_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - self.runtime_session_owner_slot_for_route(session_id, owner_route) + self.runtime_session_owner_slot_for_owner(owner) .ok()? .page_slot() .renderer_document_lifecycle_binding() @@ -2070,18 +2027,18 @@ impl CdpConnection { &mut self, session_id: Option<&str>, ) -> Result<&mut TargetRuntimeSlot, String> { - self.runtime_session_owner_slot_mut_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.runtime_session_owner_slot_mut_for_owner(&owner) } - pub(crate) fn runtime_session_owner_slot_mut_for_route( + pub(crate) fn runtime_session_owner_slot_mut_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Result<&mut TargetRuntimeSlot, String> { let renderer_inspector_session_id = - self.target_renderer_runtime_inspector_session_id_for_route(session_id, owner_route); + self.target_renderer_runtime_inspector_session_id_for_owner(owner); let slot = self - .target_session_owner_mut_for_route(session_id, owner_route) + .target_session_owner_mut_for_owner(owner) .map(TargetSessionOwnerMut::into_runtime_slot_mut) .ok_or_else(|| "NoDocumentLoaded".to_owned())?; if let Some(page) = slot.loaded_page_mut() { @@ -2094,15 +2051,15 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> Result<&TargetRuntimeSlot, String> { - self.runtime_session_owner_slot_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.runtime_session_owner_slot_for_owner(&owner) } - pub(crate) fn runtime_session_owner_slot_for_route( + pub(crate) fn runtime_session_owner_slot_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Result<&TargetRuntimeSlot, String> { - self.target_session_owner_ref_for_route(session_id, owner_route) + self.target_session_owner_ref_for_owner(owner) .map(|owner| owner.runtime_slot()) .ok_or_else(|| "NoDocumentLoaded".to_owned()) } @@ -2111,40 +2068,31 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> Option { - self.runtime_session_owner_primary_session_id_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.runtime_session_owner_primary_session_id_for_owner(&owner) } - pub(crate) fn runtime_session_owner_primary_session_id_for_route( + pub(crate) fn runtime_session_owner_primary_session_id_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - self.target_session_owner_ref_for_route(session_id, owner_route)? + self.target_session_owner_ref_for_owner(owner)? .primary_session_id() } - pub(crate) fn page_event_session_ids_for_session_owner( + pub(crate) fn page_event_session_ids_for_owner( &self, - session_id: Option<&str>, + owner: &CommandOwnerScope, ) -> Vec> { - self.page_event_session_ids_for_route(session_id, None) - } - - pub(crate) fn page_event_session_ids_for_route( - &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, - ) -> Vec> { - let Some((browser_context_id, target_id)) = - self.target_owner_identity_for_route(session_id, owner_route) + let Some((browser_context_id, target_id)) = self.target_owner_identity_for_owner(owner) else { - return vec![session_id.map(str::to_owned)]; + return vec![owner.session_id().map(str::to_owned)]; }; let Some(browser_context) = self.browser_context_by_id(&browser_context_id) else { - return vec![session_id.map(str::to_owned)]; + return vec![owner.session_id().map(str::to_owned)]; }; let Some(target_id) = target_id else { - return vec![session_id.map(str::to_owned)]; + return vec![owner.session_id().map(str::to_owned)]; }; let mut session_ids = Vec::new(); @@ -2155,7 +2103,8 @@ impl CdpConnection { .background_target(&target_id) .and_then(|target| target.session_id().map(str::to_owned)) }; - let primary_event_session_id = primary_session_id.or_else(|| session_id.map(str::to_owned)); + let primary_event_session_id = + primary_session_id.or_else(|| owner.session_id().map(str::to_owned)); session_ids.push(primary_event_session_id.clone()); for auxiliary_session_id in browser_context.auxiliary_session_ids_for_target(&target_id) { if primary_event_session_id.as_deref() != Some(auxiliary_session_id.as_str()) { @@ -2169,23 +2118,23 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> Vec> { - self.subscribed_page_event_session_ids_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.subscribed_page_event_session_ids_for_owner(&owner) } - pub(crate) fn subscribed_page_event_session_ids_for_route( + pub(crate) fn subscribed_page_event_session_ids_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Vec> { - self.page_event_session_ids_for_route(session_id, owner_route) + self.page_event_session_ids_for_owner(owner) .into_iter() .filter(|event_session_id| { - let event_owner_route = event_session_id.is_none().then_some(owner_route).flatten(); - self.target_page_session_state_for_route( - event_session_id.as_deref(), - event_owner_route, - ) - .is_some_and(|state| state.page_domain_enabled) + let event_owner = event_session_id + .as_deref() + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); + self.target_page_session_state_for_owner(&event_owner) + .is_some_and(|state| state.page_domain_enabled) }) .collect() } @@ -2198,22 +2147,20 @@ impl CdpConnection { /// identities, but must never call `page_event_session_ids_for_session_owner` /// again: doing so could route an old Page's historical event through a /// replacement Page or a newly active implicit attachment. - pub(crate) fn page_event_protocol_attachments_for_route( + pub(crate) fn page_event_protocol_attachments_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option> { - let source = - self.target_page_protocol_attachment_identity_for_route(session_id, owner_route)?; + let source = self.target_page_protocol_attachment_identity_for_owner(owner)?; let attachments = self - .subscribed_page_event_session_ids_for_route(session_id, owner_route) + .subscribed_page_event_session_ids_for_owner(owner) .into_iter() .map(|event_session_id| { - let event_owner_route = event_session_id.is_none().then_some(owner_route).flatten(); - self.target_page_protocol_attachment_identity_for_route( - event_session_id.as_deref(), - event_owner_route, - ) + let event_owner = event_session_id + .as_deref() + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); + self.target_page_protocol_attachment_identity_for_owner(&event_owner) }) .collect::>>()?; (!attachments.is_empty() @@ -2230,30 +2177,28 @@ impl CdpConnection { /// once per Inspector session. Freeze the audience at ingress so a later /// detach, target replacement, or `Runtime.enable` cannot retarget that /// historical fact. - pub(crate) fn runtime_event_protocol_attachments_for_route( + pub(crate) fn runtime_event_protocol_attachments_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option> { - let source = - self.target_page_protocol_attachment_identity_for_route(session_id, owner_route)?; + let source = self.target_page_protocol_attachment_identity_for_owner(owner)?; let attachments = self - .page_event_session_ids_for_route(session_id, owner_route) + .page_event_session_ids_for_owner(owner) .into_iter() .filter(|event_session_id| { - let event_owner_route = event_session_id.is_none().then_some(owner_route).flatten(); - self.target_runtime_session_state_for_route( - event_session_id.as_deref(), - event_owner_route, - ) - .is_some_and(|state| state.runtime_frontend_enabled) + let event_owner = event_session_id + .as_deref() + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); + self.target_runtime_session_state_for_owner(&event_owner) + .is_some_and(|state| state.runtime_frontend_enabled) }) .map(|event_session_id| { - let event_owner_route = event_session_id.is_none().then_some(owner_route).flatten(); - self.target_page_protocol_attachment_identity_for_route( - event_session_id.as_deref(), - event_owner_route, - ) + let event_owner = event_session_id + .as_deref() + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); + self.target_page_protocol_attachment_identity_for_owner(&event_owner) }) .collect::>>()?; attachments @@ -2266,34 +2211,22 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> Option { - self.runtime_session_owner_target_url_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.runtime_session_owner_target_url_for_owner(&owner) } - pub(crate) fn runtime_session_owner_target_url_for_route( + pub(crate) fn runtime_session_owner_target_url_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - Some( - self.target_session_owner_ref_for_route(session_id, owner_route)? - .target_url(), - ) + Some(self.target_session_owner_ref_for_owner(owner)?.target_url()) } - pub(crate) fn runtime_session_owner_record_initial_empty_document_url( + pub(crate) fn runtime_session_owner_record_initial_empty_document_url_for_owner( &self, - session_id: Option<&str>, + owner: &CommandOwnerScope, ) -> Option { - self.target_session_owner_ref(session_id)? - .initial_empty_document_url_if_current() - } - - pub(crate) fn runtime_session_owner_record_initial_empty_document_url_for_route( - &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, - ) -> Option { - self.target_session_owner_ref_for_route(session_id, owner_route)? + self.target_session_owner_ref_for_owner(owner)? .initial_empty_document_url_if_current() } @@ -2305,29 +2238,27 @@ impl CdpConnection { .initial_empty_document_storage_key_if_current() } - pub(crate) fn runtime_session_owner_initial_empty_document_storage_key_for_route( + pub(crate) fn runtime_session_owner_initial_empty_document_storage_key_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - self.target_session_owner_ref_for_route(session_id, owner_route)? + self.target_session_owner_ref_for_owner(owner)? .initial_empty_document_storage_key_if_current() } - pub(crate) fn runtime_session_owner_record_is_on_initial_empty_document_for_route( + pub(crate) fn runtime_session_owner_record_is_on_initial_empty_document_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - self.target_session_owner_ref_for_route(session_id, owner_route)? + self.target_session_owner_ref_for_owner(owner)? .is_on_initial_empty_document() } - pub(crate) fn runtime_session_owner_initial_empty_document_has_pending_cross_document_navigation( + pub(crate) fn runtime_session_owner_initial_empty_document_has_pending_cross_document_navigation_for_owner( &self, - session_id: Option<&str>, + owner: &CommandOwnerScope, ) -> bool { - self.target_session_owner_ref(session_id) + self.target_session_owner_ref_for_owner(owner) .is_some_and(|owner| { owner.initial_empty_document_has_pending_cross_document_navigation() }) @@ -2337,26 +2268,25 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> Option<(String, String, String, String)> { - self.target_session_owner_frame_tree_identity_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.target_session_owner_frame_tree_identity_for_owner(&owner) } - pub(crate) fn target_session_owner_frame_tree_identity_for_route( + pub(crate) fn target_session_owner_frame_tree_identity_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option<(String, String, String, String)> { Some( - self.target_session_owner_ref_for_route(session_id, owner_route)? + self.target_session_owner_ref_for_owner(owner)? .frame_tree_identity(), ) } - pub(crate) fn target_session_owner_frame_tree_loader_id_for_route( + pub(crate) fn target_session_owner_frame_tree_loader_id_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - self.target_session_owner_ref_for_route(session_id, owner_route)? + self.target_session_owner_ref_for_owner(owner)? .frame_tree_loader_id() } @@ -2368,12 +2298,11 @@ impl CdpConnection { .emulated_device_metrics() } - pub(crate) fn target_session_owner_emulated_device_metrics_for_route( + pub(crate) fn target_session_owner_emulated_device_metrics_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - self.target_session_owner_ref_for_route(session_id, owner_route)? + self.target_session_owner_ref_for_owner(owner)? .emulated_device_metrics() } @@ -2381,28 +2310,28 @@ impl CdpConnection { &mut self, session_id: Option<&str>, ) -> Option<(usize, Vec)> { - self.target_session_owner_navigation_history_snapshot_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.target_session_owner_navigation_history_snapshot_for_owner(&owner) } - pub(crate) fn target_session_owner_navigation_history_snapshot_for_route( + pub(crate) fn target_session_owner_navigation_history_snapshot_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option<(usize, Vec)> { - self.target_session_owner_mut_for_route(session_id, owner_route)? + self.target_session_owner_mut_for_owner(owner)? .navigation_history_snapshot() } - pub(crate) fn apply_renderer_document_title_for_session_owner( + pub(crate) fn apply_renderer_document_title_for_owner( &mut self, - session_id: Option<&str>, + owner: &CommandOwnerScope, change: &moli_core::RendererDocumentTitleChanged, ) -> Option { - self.target_root_document_protocol_attachment_identity_for_session( - session_id, + self.target_root_document_protocol_attachment_identity_for_owner( + owner, change.source_document, )?; - self.target_session_owner_mut(session_id)? + self.target_session_owner_mut_for_owner(owner)? .apply_renderer_document_title(change.title.clone()) } @@ -2415,12 +2344,11 @@ impl CdpConnection { .navigation_history_entry_url(entry_id) } - pub(crate) fn reset_navigation_history_for_route( + pub(crate) fn reset_navigation_history_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - self.target_session_owner_mut_for_route(session_id, owner_route)? + self.target_session_owner_mut_for_owner(owner)? .reset_navigation_history() } @@ -2432,32 +2360,30 @@ impl CdpConnection { .can_reset_navigation_history() } - pub(crate) fn mark_next_navigation_history_replace_current_for_route( + pub(crate) fn mark_next_navigation_history_replace_current_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option<()> { - self.target_session_owner_mut_for_route(session_id, owner_route)? + self.target_session_owner_mut_for_owner(owner)? .mark_next_navigation_history_replace_current() } - pub(crate) fn mark_next_navigation_history_traverse_to_entry_for_route( + pub(crate) fn mark_next_navigation_history_traverse_to_entry_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, entry_id: i32, ) -> Option<()> { - self.target_session_owner_mut_for_route(session_id, owner_route)? + self.target_session_owner_mut_for_owner(owner)? .mark_next_navigation_history_traverse_to_entry(entry_id) } - pub(crate) fn record_same_document_navigation_for_session_owner( + pub(crate) fn record_same_document_navigation_for_owner( &mut self, - session_id: Option<&str>, + owner: &CommandOwnerScope, url: &Url, history_update: moli_core::page::SameDocumentHistoryUpdate, ) -> Option { - self.target_session_owner_mut(session_id)? + self.target_session_owner_mut_for_owner(owner)? .record_same_document_navigation(url, history_update) } @@ -2465,21 +2391,21 @@ impl CdpConnection { &mut self, session_id: Option<&str>, ) -> Option> { - self.target_session_owner_mut_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.target_session_owner_mut_for_owner(&owner) } - pub(super) fn target_session_owner_mut_for_route( + pub(super) fn target_session_owner_mut_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option> { - let owner = self.target_session_owner_for_route(session_id, owner_route)?; - self.browser_context_by_id_mut(&owner.browser_context_id) + let resolved = self.target_session_owner_for_owner(owner)?; + self.browser_context_by_id_mut(&resolved.browser_context_id) .map(|browser_context| TargetSessionOwnerMut { browser_context, - target_id: owner.target_id, - command_session_id: session_id.map(str::to_owned), - session_key: owner.session_key, + target_id: resolved.target_id, + command_session_id: owner.session_id().map(str::to_owned), + session_key: resolved.session_key, }) } @@ -2487,20 +2413,20 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> Option> { - self.target_session_owner_ref_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.target_session_owner_ref_for_owner(&owner) } - pub(super) fn target_session_owner_ref_for_route( + pub(super) fn target_session_owner_ref_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option> { - let owner = self.target_session_owner_for_route(session_id, owner_route)?; - self.browser_context_by_id(&owner.browser_context_id) + let resolved = self.target_session_owner_for_owner(owner)?; + self.browser_context_by_id(&resolved.browser_context_id) .map(|browser_context| TargetSessionOwnerRef { browser_context, - target_id: owner.target_id, - session_key: owner.session_key, + target_id: resolved.target_id, + session_key: resolved.session_key, }) } @@ -2512,14 +2438,12 @@ impl CdpConnection { self.target_session_owner_mut(session_id).map(f) } - pub(super) fn with_target_session_owner_mut_for_route( + pub(super) fn with_target_session_owner_mut_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, f: impl FnOnce(TargetSessionOwnerMut<'_>) -> R, ) -> Option { - self.target_session_owner_mut_for_route(session_id, owner_route) - .map(f) + self.target_session_owner_mut_for_owner(owner).map(f) } } @@ -3519,10 +3443,7 @@ mod tests { let current = conn .target_page_residence_identity_for_session(Some("SID-page-residence")) .expect("active target should expose its Page residence identity"); - assert!(conn.target_page_residence_identity_is_current_for_session( - Some("SID-page-residence"), - ¤t, - )); + assert!(conn.target_page_residence_identity_is_current(¤t)); for stale in [ TargetPageResidenceIdentity::new( @@ -3542,10 +3463,7 @@ mod tests { ), ] { assert!( - !conn.target_page_residence_identity_is_current_for_session( - Some("SID-page-residence"), - &stale, - ), + !conn.target_page_residence_identity_is_current(&stale), "every Page residence identity component must participate in authorization" ); } @@ -3578,9 +3496,8 @@ mod tests { "a reservation must not masquerade as the current Page" ); assert!( - conn.pending_target_page_residence_identity_for_route( - Some("SID-pending-residence"), - None, + conn.pending_target_page_residence_identity_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-pending-residence"), ) .is_some(), "the future Page attachment should remain explicitly addressable" @@ -3607,7 +3524,7 @@ mod tests { .expect("browser context") .set_active_target_id("TID-replacement"); assert!( - conn.target_page_residence_identity_is_current_for_session(None, &original), + conn.target_page_residence_identity_is_current(&original), "changing visibility must not retire the original stable Page residence" ); assert_ne!( @@ -3755,11 +3672,13 @@ mod tests { }) .expect("Runtime-enabled auxiliary session should be mutable"); assert_eq!( - conn.runtime_event_protocol_attachments_for_route(Some("SID-runtime-a"), None) - .expect("the current Page should expose its Runtime audience") - .into_iter() - .map(|attachment| attachment.session_id().map(str::to_owned)) - .collect::>(), + conn.runtime_event_protocol_attachments_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-runtime-a") + ) + .expect("the current Page should expose its Runtime audience") + .into_iter() + .map(|attachment| attachment.session_id().map(str::to_owned)) + .collect::>(), vec![Some("SID-runtime-b".to_owned())], "a disabled primary must not hide the enabled peer attachment" ); @@ -3769,11 +3688,13 @@ mod tests { }) .expect("Runtime-enabled primary session should be mutable"); assert_eq!( - conn.runtime_event_protocol_attachments_for_route(Some("SID-runtime-b"), None) - .expect("the current Page should expose its Runtime audience") - .into_iter() - .map(|attachment| attachment.session_id().map(str::to_owned)) - .collect::>(), + conn.runtime_event_protocol_attachments_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-runtime-b") + ) + .expect("the current Page should expose its Runtime audience") + .into_iter() + .map(|attachment| attachment.session_id().map(str::to_owned)) + .collect::>(), vec![ Some("SID-runtime-a".to_owned()), Some("SID-runtime-b".to_owned()), diff --git a/moli-protocol/src/conn/command_owner_scope.rs b/moli-protocol/src/conn/command_owner_scope.rs index 372170e252..769a004988 100644 --- a/moli-protocol/src/conn/command_owner_scope.rs +++ b/moli-protocol/src/conn/command_owner_scope.rs @@ -22,18 +22,6 @@ impl CommandOwnerScope { } } - pub(crate) fn capture_for_route( - conn: &CdpConnection, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, - ) -> Self { - match (session_id, owner_route) { - (Some(session_id), _) => Self::for_session(session_id), - (None, Some(route)) => Self::for_route(route.clone()), - (None, None) => Self::capture(conn, None), - } - } - fn capture_default_route(conn: &CdpConnection) -> CdpSessionRoute { let Some(browser_context) = conn.browser_context.as_ref() else { return CdpSessionRoute::Browser; @@ -90,17 +78,23 @@ impl CommandOwnerScope { } } - /// Returns the explicit route captured for a command without a session. + /// Resolves this command's single authority to its current CDP route. /// - /// A concrete CDP session remains authoritative through `session_id`; the - /// route freezes Chromium's primary Page attachment at command admission - /// whenever no more explicit route was supplied. `Browser` and - /// `BrowserContext` remain explicit authorities rather than a missing - /// owner that can silently acquire a later active Page. - pub(crate) fn session_owner_route(&self) -> Option<&CdpSessionRoute> { + /// Session owners resolve through the attachment registry. Route owners + /// retain the exact route captured at command admission. Callers therefore + /// cannot express the old invalid combinations of an absent authority or + /// both a session and an explicit route. + pub(crate) fn resolve_route(&self, conn: &CdpConnection) -> Option { + match &self.identity { + CommandOwnerIdentity::Session(session_id) => conn.session_route(Some(session_id)), + CommandOwnerIdentity::Route(route) => Some(route.clone()), + } + } + + pub(crate) fn explicit_route(&self) -> Option<&CdpSessionRoute> { match &self.identity { - CommandOwnerIdentity::Route(route) => Some(route), CommandOwnerIdentity::Session(_) => None, + CommandOwnerIdentity::Route(route) => Some(route), } } } @@ -108,7 +102,19 @@ impl CommandOwnerScope { #[cfg(test)] mod tests { use super::*; - use crate::conn::BrowserContext; + use crate::conn::{BrowserContext, PageTargetHost}; + use crate::devtools_runtime::{ + DevToolsCommandContext, DevToolsProtocol, DevToolsSessionId, DevToolsTargetId, + }; + + fn page_context(session_id: &str, target_id: &str) -> DevToolsCommandContext { + DevToolsCommandContext { + protocol: DevToolsProtocol::Cdp, + session_id: Some(DevToolsSessionId::from(session_id)), + target_id: Some(DevToolsTargetId::from(target_id)), + browser_context_id: None, + } + } #[test] fn root_page_scope_freezes_the_concrete_active_target() { @@ -124,7 +130,7 @@ mod tests { .set_active_target_id("TID-replacement"); assert_eq!( - conn.target_owner_identity_for_route(scope.session_id(), scope.session_owner_route(),), + conn.target_owner_identity_for_owner(&scope,), Some(("BID-scope".to_owned(), Some("TID-original".to_owned()))) ); } @@ -135,7 +141,7 @@ mod tests { let scope = CommandOwnerScope::capture(&conn, None); - assert_eq!(scope.session_owner_route(), Some(&CdpSessionRoute::Browser)); + assert_eq!(scope.explicit_route(), Some(&CdpSessionRoute::Browser)); } #[test] @@ -146,10 +152,70 @@ mod tests { let scope = CommandOwnerScope::capture(&conn, None); assert_eq!( - scope.session_owner_route(), + scope.explicit_route(), Some(&CdpSessionRoute::BrowserContext { browser_context_id: "BID-empty".to_owned(), }) ); } + + #[test] + fn explicit_target_preserves_matching_auxiliary_session_authority() { + let mut conn = CdpConnection::default(); + let mut browser_context = BrowserContext::new_with_page_for_test("BID-owner", "TID-owner"); + browser_context.attach_active_session("SID-primary"); + assert!( + browser_context + .assign_auxiliary_session_to_target("TID-owner", "SID-auxiliary".to_owned(),) + ); + conn.browser_context = Some(browser_context); + + let owner = conn + .command_owner_scope_for_devtools_context(&page_context("SID-auxiliary", "TID-owner")) + .expect("matching auxiliary attachment should own the command"); + + assert_eq!(owner.session_id(), Some("SID-auxiliary")); + assert!(owner.explicit_route().is_none()); + } + + #[test] + fn explicit_target_routes_protocol_neutral_session_and_rejects_wrong_cdp_attachment() { + let mut conn = CdpConnection::default(); + let mut browser_context = + BrowserContext::new_with_page_for_test("BID-owner", "TID-primary"); + browser_context.attach_active_session("SID-primary"); + assert!( + browser_context.insert_page_target_host(PageTargetHost::with_url( + "TID-background".to_owned(), + Some("SID-background".to_owned()), + "about:blank".to_owned(), + )) + ); + conn.browser_context = Some(browser_context); + + let protocol_neutral = conn + .command_owner_scope_for_devtools_context(&page_context( + "webdriver-session", + "TID-background", + )) + .expect("non-CDP session should use its explicit target"); + assert_eq!(protocol_neutral.session_id(), None); + assert_eq!( + protocol_neutral.explicit_route(), + Some(&CdpSessionRoute::PageTarget { + browser_context_id: "BID-owner".to_owned(), + target_id: "TID-background".to_owned(), + session_key: moli_page_types::DevToolsSessionKey::Primary, + }) + ); + + assert!( + conn.command_owner_scope_for_devtools_context(&page_context( + "SID-primary", + "TID-background", + )) + .is_none(), + "a real CDP attachment cannot address another target", + ); + } } diff --git a/moli-protocol/src/conn/devtools_command.rs b/moli-protocol/src/conn/devtools_command.rs index 5c1c4f8fab..23887abec6 100644 --- a/moli-protocol/src/conn/devtools_command.rs +++ b/moli-protocol/src/conn/devtools_command.rs @@ -452,10 +452,7 @@ impl CdpConnection { } let mut listener_events = Vec::new(); if has_default_bidi_channel_preload_script - || self.target_owner_has_bidi_channel_preload_script_for_route( - command_owner.session_id(), - command_owner.session_owner_route(), - ) + || self.target_owner_has_bidi_channel_preload_script_for_owner(&command_owner) { let mut execution_context_ids = initial_runtime_execution_context_ids; // Target lifecycle creation can materialize initial about:blank without Runtime.enable; diff --git a/moli-protocol/src/conn/dispatch_tests.rs b/moli-protocol/src/conn/dispatch_tests.rs index 9cc5202716..6b4cf1e3c7 100644 --- a/moli-protocol/src/conn/dispatch_tests.rs +++ b/moli-protocol/src/conn/dispatch_tests.rs @@ -629,7 +629,9 @@ async fn devtools_script_navigation_exact_cursor_rejects_replaced_page_owner_act .target_session_route_for_target_id(target_id.as_str()) .expect("created target route"); ctx.conn - .runtime_session_owner_slot_mut_for_route(None, Some(&route)) + .runtime_session_owner_slot_mut_for_owner(&crate::conn::CommandOwnerScope::for_route( + route.clone(), + )) .expect("created target runtime slot") .replace_page_attachment_id_for_test(); @@ -708,9 +710,8 @@ async fn bidi_fetch_control_resolves_background_request_owner() { )); conn.browser_context = Some(browser_context); - conn.register_pending_fetch_navigation_request_for_route( - Some("SID-background"), - None, + conn.register_pending_fetch_navigation_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-background"), PendingFetchNavigation { fetch_request_id: "FETCH-background".to_owned(), interception_session_id: Some("bidi-session-1".to_owned()), @@ -1588,7 +1589,9 @@ async fn devtools_runtime_command_uses_background_initial_document_without_resol let route = conn .target_session_route_for_target_id(second_target_id.as_str()) .expect("background target route"); - conn.navigation_load_inputs_for_route(None, Some(&route)) + conn.navigation_load_inputs_for_owner(&crate::conn::CommandOwnerScope::for_route( + route.clone(), + )) }; assert!( background_load_inputs @@ -1788,7 +1791,9 @@ async fn protocol_neutral_await_promise_keeps_background_owner_route_across_pend .expect("active target route"); assert!( !conn - .target_devtools_session_state_for_route(None, Some(&active_route)) + .target_devtools_session_state_for_owner(&crate::conn::CommandOwnerScope::for_route( + active_route.clone() + )) .is_some_and(crate::conn::DevToolsSessionState::has_pending_inspector_awaits), "internal id 0 pending await must not be registered on the active owner" ); @@ -1797,8 +1802,10 @@ async fn protocol_neutral_await_promise_keeps_background_owner_route_across_pend .target_session_route_for_target_id(second_target_id.as_str()) .expect("background target route"); assert!( - conn.target_devtools_session_state_for_route(None, Some(&background_route)) - .is_some_and(crate::conn::DevToolsSessionState::has_pending_inspector_awaits), + conn.target_devtools_session_state_for_owner(&crate::conn::CommandOwnerScope::for_route( + background_route.clone() + )) + .is_some_and(crate::conn::DevToolsSessionState::has_pending_inspector_awaits), "internal id 0 pending await must be registered on the targeted background owner" ); @@ -1851,7 +1858,8 @@ async fn protocol_neutral_await_promise_keeps_background_owner_route_across_pend #[tokio::test] async fn pending_runtime_binding_page_phase_keeps_background_owner_route_across_completion() { - let mut conn = CdpConnection::new(); + let mut ctx = crate::testing::TestContext::from_conn(CdpConnection::new()); + let conn = &mut ctx.conn; let context = DevToolsCommandContext { protocol: DevToolsProtocol::WebDriverBidi, session_id: Some(DevToolsSessionId::from("bidi-binding-owner-route")), @@ -1861,7 +1869,7 @@ async fn pending_runtime_binding_page_phase_keeps_background_owner_route_across_ let (first_result, _) = crate::domains::target::execute_immediate_devtools_target_command_with_protocol_events( - &mut conn, + conn, DevToolsCommand::CreateTarget(DevToolsCreateTargetCommand { context: context.clone(), url: "about:blank".to_owned(), @@ -1875,7 +1883,7 @@ async fn pending_runtime_binding_page_phase_keeps_background_owner_route_across_ panic!("expected create target result"); }; let first_target_id = first_result.target_id; - ensure_initial_document_for_target_id_for_test(&mut conn, &first_target_id).await; + ensure_initial_document_for_target_id_for_test(conn, &first_target_id).await; let (second_result, _) = conn .execute_devtools_command(DevToolsCommand::CreateTarget(DevToolsCreateTargetCommand { @@ -1892,7 +1900,7 @@ async fn pending_runtime_binding_page_phase_keeps_background_owner_route_across_ panic!("expected create target result"); }; let second_target_id = second_result.target_id; - ensure_initial_document_for_target_id_for_test(&mut conn, &second_target_id).await; + ensure_initial_document_for_target_id_for_test(conn, &second_target_id).await; let first_context = DevToolsCommandContext { target_id: Some(first_target_id.clone()), @@ -1904,7 +1912,7 @@ async fn pending_runtime_binding_page_phase_keeps_background_owner_route_across_ }; assert_eq!( evaluate_string_for_test( - &mut conn, + conn, first_context, "globalThis.__bindingOwnerProbe = 'active'; globalThis.__bindingOwnerProbe", "active binding owner marker", @@ -1914,7 +1922,7 @@ async fn pending_runtime_binding_page_phase_keeps_background_owner_route_across_ ); assert_eq!( evaluate_string_for_test( - &mut conn, + conn, second_context, "globalThis.__bindingOwnerProbe = 'background'; globalThis.__bindingOwnerProbe", "background binding owner marker", @@ -1924,25 +1932,15 @@ async fn pending_runtime_binding_page_phase_keeps_background_owner_route_across_ ); let background_session = - attach_page_session_for_test(&mut conn, second_target_id.as_str()).await; - let raw = serde_json::to_string(&json!({ + attach_page_session_for_test(&mut ctx.conn, second_target_id.as_str()).await; + ctx.process_and_wait_for_response_async(json!({ "id": 1269, "method": "Runtime.addBinding", "params": { "name": "backgroundRouteBinding" }, - "sessionId": background_session + "sessionId": background_session.clone() })) - .unwrap(); - let pending = match conn.start_command_dispatch(&raw) { - CdpCommandTaskStep::Pending(pending) => pending, - CdpCommandTaskStep::Complete(outcome) => { - panic!( - "background Runtime.addBinding should pend through renderer binding state apply: {:?}", - outcome.into_parts().0 - ) - } - }; - - let messages = complete_command_task_for_test(&mut conn, *pending).await; + .await; + let messages = ctx.take_all(); assert!( messages .iter() @@ -1950,7 +1948,8 @@ async fn pending_runtime_binding_page_phase_keeps_background_owner_route_across_ "Runtime.addBinding should complete successfully on the original background owner: {messages:?}" ); assert!( - conn.target_devtools_session_state_for_session(None) + ctx.conn + .target_devtools_session_state_for_session(None) .is_none_or(|state| state .runtime_bindings .iter() @@ -1958,7 +1957,8 @@ async fn pending_runtime_binding_page_phase_keeps_background_owner_route_across_ "binding state apply completion must not write the active owner" ); assert!( - conn.target_devtools_session_state_for_session(Some(&background_session)) + ctx.conn + .target_devtools_session_state_for_session(Some(&background_session)) .is_some_and(|state| state .runtime_bindings .iter() @@ -1966,7 +1966,8 @@ async fn pending_runtime_binding_page_phase_keeps_background_owner_route_across_ "binding state apply completion should persist on the original background owner" ); assert_eq!( - conn.browser_context + ctx.conn + .browser_context .as_ref() .expect("browser context") .active_target_id(), @@ -4085,9 +4086,10 @@ async fn set_file_input_files_shared_id_uses_renderer_binding_without_protocol_r .await; let fake_shared_id = crate::devtools_runtime::webdriver_bidi_node_shared_id_for_backend_node_id(backend_node_id); + let owner = CommandOwnerScope::capture(&ctx.conn, None); ctx.conn - .register_document_bidi_node_binding_for_session_owner_async( - None, + .register_document_bidi_node_binding_for_owner_async( + &owner, fake_shared_id.as_str(), backend_node_id, ) @@ -4150,9 +4152,10 @@ async fn locate_nodes_start_node_shared_id_uses_renderer_binding_without_protoco .await; let fake_shared_id = crate::devtools_runtime::webdriver_bidi_node_shared_id_for_backend_node_id(backend_node_id); + let owner = CommandOwnerScope::capture(&ctx.conn, None); ctx.conn - .register_document_bidi_node_binding_for_session_owner_async( - None, + .register_document_bidi_node_binding_for_owner_async( + &owner, fake_shared_id.as_str(), backend_node_id, ) @@ -4198,9 +4201,10 @@ async fn call_function_shared_id_uses_renderer_binding_without_protocol_registry .await; let fake_shared_id = crate::devtools_runtime::webdriver_bidi_node_shared_id_for_backend_node_id(backend_node_id); + let owner = CommandOwnerScope::capture(&ctx.conn, None); ctx.conn - .register_document_bidi_node_binding_for_session_owner_async( - None, + .register_document_bidi_node_binding_for_owner_async( + &owner, fake_shared_id.as_str(), backend_node_id, ) @@ -4640,7 +4644,9 @@ async fn devtools_command_applies_known_user_context_viewport_default() { .target_session_route_for_target_id(create_result.target_id.as_str()) .expect("created target route"); let inherited_metrics = conn - .target_session_owner_emulated_device_metrics_for_route(None, Some(&route)) + .target_session_owner_emulated_device_metrics_for_owner( + &crate::conn::CommandOwnerScope::for_route(route.clone()), + ) .expect("new target should inherit userContext default metrics"); assert_eq!( ( @@ -6245,7 +6251,9 @@ async fn devtools_command_executes_user_context_preload_without_default_leakage( .expect("custom userContext target route"); assert!( ctx.conn - .navigation_load_inputs_for_route(None, Some(&custom_route)) + .navigation_load_inputs_for_owner(&crate::conn::CommandOwnerScope::for_route( + custom_route.clone() + )) .document_start_scripts .iter() .any(|script| script.source.contains("__bidiUserContextPreload")), @@ -8330,7 +8338,9 @@ async fn pending_emulation_timezone_keeps_background_owner_route_across_completi "background timezone", "background Emulation completion should preserve the captured owner" ); - let background_inputs = conn.navigation_load_inputs_for_route(None, Some(&background_route)); + let background_inputs = conn.navigation_load_inputs_for_owner( + &crate::conn::CommandOwnerScope::for_route(background_route.clone()), + ); assert_eq!(background_inputs.timezone_override.as_deref(), Some("UTC")); assert!( conn.navigation_load_inputs_for_session_owner(None) @@ -8730,8 +8740,9 @@ async fn devtools_network_intercept_commands_route_to_fetch_owner() { .into_parts(); auth_only_result.expect("auth-only add intercept should succeed"); let auth_url = url::Url::parse("https://example.test/protected").unwrap(); + let owner = CommandOwnerScope::capture(&conn, None); let preflight = conn - .prepare_navigation_request_for_route(None, None, &auth_url, None, false) + .prepare_navigation_request_for_owner(&owner, &auth_url, None, false) .expect("auth-only intercept should prepare navigation preflight"); assert!(preflight.document_auth_required); assert_eq!( diff --git a/moli-protocol/src/conn/downloads.rs b/moli-protocol/src/conn/downloads.rs index 50b4378d8e..6a6579b838 100644 --- a/moli-protocol/src/conn/downloads.rs +++ b/moli-protocol/src/conn/downloads.rs @@ -19,8 +19,8 @@ use url::Url; use super::{ BackgroundProtocolEvent, BrowserDownloadBehaviorSettings, CdpConnection, - CommandDispatchContext, CompletedDownloadBody, CompletedDownloadBodyArtifact, - NavigationDispatchState, output::BackgroundEventSender, + CommandDispatchContext, CommandOwnerScope, CompletedDownloadBody, + CompletedDownloadBodyArtifact, NavigationDispatchState, output::BackgroundEventSender, }; #[derive(Clone, Default)] @@ -227,13 +227,13 @@ impl CdpConnection { pub(crate) async fn handle_pending_download_activation_background_events_async( &mut self, out: &mut Vec, - session_id: Option<&str>, + owner: &CommandOwnerScope, activation: RendererPendingDownloadActivation, command_context: &mut CommandDispatchContext, ) -> Result<(), String> { self.handle_pending_download_activation_with_event_route_async( out, - session_id, + owner, activation, true, command_context, @@ -244,13 +244,13 @@ impl CdpConnection { pub(crate) async fn handle_pending_download_activation_inline_async( &mut self, out: &mut Vec, - session_id: Option<&str>, + owner: &CommandOwnerScope, activation: RendererPendingDownloadActivation, command_context: &mut CommandDispatchContext, ) -> Result<(), String> { self.handle_pending_download_activation_with_event_route_async( out, - session_id, + owner, activation, false, command_context, @@ -261,14 +261,12 @@ impl CdpConnection { async fn handle_pending_download_activation_with_event_route_async( &mut self, out: &mut Vec, - session_id: Option<&str>, + owner: &CommandOwnerScope, activation: RendererPendingDownloadActivation, allow_background_events: bool, command_context: &mut CommandDispatchContext, ) -> Result<(), String> { - if let Some(events) = - self.denied_pending_download_activation_events(session_id, &activation)? - { + if let Some(events) = self.denied_pending_download_activation_events(owner, &activation)? { if allow_background_events && let Some(sender) = self.background_event_sender() { if command_context.response_flush().is_active() { command_context.extend_post_response_events(events); @@ -282,8 +280,7 @@ impl CdpConnection { } if activation.response.is_some() { - let Some(prepared) = - self.prepare_prefetched_download_activation(session_id, activation)? + let Some(prepared) = self.prepare_prefetched_download_activation(owner, activation)? else { return Ok(()); }; @@ -306,8 +303,7 @@ impl CdpConnection { return Ok(()); } - let Some(prepared) = self.prepare_pending_download_activation(session_id, activation)? - else { + let Some(prepared) = self.prepare_pending_download_activation(owner, activation)? else { return Ok(()); }; @@ -397,10 +393,10 @@ impl CdpConnection { fn prepare_pending_download_activation( &mut self, - session_id: Option<&str>, + command_owner: &CommandOwnerScope, activation: RendererPendingDownloadActivation, ) -> Result, String> { - let Some(owner) = self.pending_download_owner_context(session_id) else { + let Some(owner) = self.pending_download_owner_context(command_owner) else { return Ok(None); }; let Some(settings) = @@ -434,7 +430,8 @@ impl CdpConnection { download_root, guid, behavior: settings.behavior, - event_route: self.download_event_route(session_id, settings.automation_events_enabled), + event_route: self + .download_event_route(command_owner, settings.automation_events_enabled), suggested_filename_hint: activation.suggested_filename, cancel_handle, registry: self.download_registry.clone(), @@ -443,10 +440,10 @@ impl CdpConnection { fn denied_pending_download_activation_events( &mut self, - session_id: Option<&str>, + command_owner: &CommandOwnerScope, activation: &RendererPendingDownloadActivation, ) -> Result>, String> { - let Some(owner) = self.pending_download_owner_context(session_id) else { + let Some(owner) = self.pending_download_owner_context(command_owner) else { return Ok(None); }; let settings = self @@ -457,7 +454,8 @@ impl CdpConnection { { return Ok(None); } - let event_route = self.download_event_route(session_id, settings.automation_events_enabled); + let event_route = + self.download_event_route(command_owner, settings.automation_events_enabled); if !event_route.has_observers() { return Ok(Some(Vec::new())); } @@ -496,10 +494,10 @@ impl CdpConnection { fn prepare_prefetched_download_activation( &mut self, - session_id: Option<&str>, + command_owner: &CommandOwnerScope, activation: RendererPendingDownloadActivation, ) -> Result, String> { - let Some(owner) = self.pending_download_owner_context(session_id) else { + let Some(owner) = self.pending_download_owner_context(command_owner) else { return Ok(None); }; let Some(settings) = @@ -529,7 +527,8 @@ impl CdpConnection { download_root, guid: generate_download_guid()?, behavior: settings.behavior, - event_route: self.download_event_route(session_id, settings.automation_events_enabled), + event_route: self + .download_event_route(command_owner, settings.automation_events_enabled), registry: self.download_registry.clone(), })) } @@ -540,13 +539,9 @@ impl CdpConnection { final_url: Url, body_artifact: CompletedDownloadBodyArtifact, ) -> Result, String> { - let owner_context_id = state - .session_id - .as_deref() - .and_then(|session_id| { - self.target_owner_identity_for_session(Some(session_id)) - .map(|(browser_context_id, _)| browser_context_id) - }) + let owner_context_id = self + .target_owner_identity_for_owner(&state.owner) + .map(|(browser_context_id, _)| browser_context_id) .or_else(|| self.browser_context.as_ref().map(|bc| bc.id.clone())); let Some(settings) = self.effective_download_behavior_for_browser_context(owner_context_id.as_deref()) @@ -570,10 +565,8 @@ impl CdpConnection { download_root, guid: generate_download_guid()?, behavior: settings.behavior, - event_route: self.download_event_route( - state.session_id.as_deref(), - settings.automation_events_enabled, - ), + event_route: self + .download_event_route(&state.owner, settings.automation_events_enabled), registry: self.download_registry.clone(), })) } @@ -621,9 +614,9 @@ impl CdpConnection { fn pending_download_owner_context( &self, - session_id: Option<&str>, + owner: &CommandOwnerScope, ) -> Option { - let (browser_context_id, target_id) = self.target_owner_identity_for_session(session_id)?; + let (browser_context_id, target_id) = self.target_owner_identity_for_owner(owner)?; let browser_context = self.browser_context_by_id(&browser_context_id)?; let frame_id = target_id .clone() @@ -634,7 +627,7 @@ impl CdpConnection { .map(|target_id| browser_context.effective_extra_headers_for_target(target_id)) .unwrap_or_else(|| browser_context.effective_extra_headers()); let initiator_url = self - .runtime_session_owner_slot(session_id) + .runtime_session_owner_slot_for_owner(owner) .ok() .and_then(|slot| slot.loaded_page().map(|page| page.final_url().clone())); Some(PendingDownloadOwnerContext { @@ -662,11 +655,11 @@ impl CdpConnection { fn download_event_route( &self, - session_id: Option<&str>, + owner: &CommandOwnerScope, automation_events_enabled: bool, ) -> DownloadEventRoute { let page_observers = self - .page_event_session_ids_for_session_owner(session_id) + .page_event_session_ids_for_owner(owner) .into_iter() .filter_map(|event_session_id| { self.page_domain_subscription_generation_for_session_owner( @@ -1497,7 +1490,10 @@ mod tests { use moli_fetch::FetchCancelHandle; use crate::{ - conn::{BackgroundProtocolEvent, BrowserContext, CdpConnection, PageTargetHost}, + conn::{ + BackgroundProtocolEvent, BrowserContext, CdpConnection, CommandOwnerScope, + PageTargetHost, + }, devtools_runtime::AutomationEvent, }; @@ -1554,7 +1550,7 @@ mod tests { connection.browser_context = Some(browser_context); let owner = connection - .pending_download_owner_context(Some("SID-background")) + .pending_download_owner_context(&CommandOwnerScope::for_session("SID-background")) .expect("background session must resolve its Page target"); assert_eq!(owner.frame_id, "TID-background"); assert_eq!( diff --git a/moli-protocol/src/conn/fetch_support.rs b/moli-protocol/src/conn/fetch_support.rs index 51696d13bf..6736a4c47f 100644 --- a/moli-protocol/src/conn/fetch_support.rs +++ b/moli-protocol/src/conn/fetch_support.rs @@ -5,7 +5,7 @@ use url::Url; use super::body_spool::ensure_materialize_limit; use super::{ - CapturedBody, CapturedBodyWriter, CdpConnection, CdpSessionRoute, DocumentNavigationToken, + CapturedBody, CapturedBodyWriter, CdpConnection, CommandOwnerScope, DocumentNavigationToken, NavigationDispatchState, NavigationLoadOutcome, PausedResponsePreparedDocument, }; use crate::devtools_runtime::{DevToolsNetworkInterceptId, DevToolsNetworkResourceType}; @@ -2056,9 +2056,9 @@ impl CdpConnection { intercept_response: bool, handle_auth_requests: bool, ) -> Result { - self.continue_pending_subresource_fetch_for_route_async( - session_id, - None, + let owner = CommandOwnerScope::capture(self, session_id); + self.continue_pending_subresource_fetch_for_owner_async( + &owner, internal_id, url, method, @@ -2070,10 +2070,9 @@ impl CdpConnection { .await } - pub(crate) async fn continue_pending_subresource_fetch_for_route_async( + pub(crate) async fn continue_pending_subresource_fetch_for_owner_async( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, internal_id: u64, url: Option, method: Option, @@ -2083,7 +2082,7 @@ impl CdpConnection { handle_auth_requests: bool, ) -> Result { let page = self - .runtime_session_owner_slot_mut_for_route(session_id, owner_route)? + .runtime_session_owner_slot_mut_for_owner(owner)? .loaded_page_mut() .ok_or_else(|| "NoDocumentLoaded".to_owned())?; page.continue_pending_subresource_fetch_async( @@ -2114,19 +2113,19 @@ impl CdpConnection { internal_id: u64, auth: SubresourceAuthCredentials, ) -> Result { - self.continue_pending_subresource_auth_for_route_async(session_id, None, internal_id, auth) + let owner = CommandOwnerScope::capture(self, session_id); + self.continue_pending_subresource_auth_for_owner_async(&owner, internal_id, auth) .await } - pub(crate) async fn continue_pending_subresource_auth_for_route_async( + pub(crate) async fn continue_pending_subresource_auth_for_owner_async( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, internal_id: u64, auth: SubresourceAuthCredentials, ) -> Result { let page = self - .runtime_session_owner_slot_mut_for_route(session_id, owner_route)? + .runtime_session_owner_slot_mut_for_owner(owner)? .loaded_page_mut() .ok_or_else(|| "NoDocumentLoaded".to_owned())?; page.continue_pending_subresource_auth_async(internal_id, auth) @@ -2149,24 +2148,19 @@ impl CdpConnection { internal_id: u64, error_text: String, ) -> Result, String> { - self.fail_pending_subresource_auth_for_route_async( - session_id, - None, - internal_id, - error_text, - ) - .await + let owner = CommandOwnerScope::capture(self, session_id); + self.fail_pending_subresource_auth_for_owner_async(&owner, internal_id, error_text) + .await } - pub(crate) async fn fail_pending_subresource_auth_for_route_async( + pub(crate) async fn fail_pending_subresource_auth_for_owner_async( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, internal_id: u64, error_text: String, ) -> Result, String> { let page = self - .runtime_session_owner_slot_mut_for_route(session_id, owner_route)? + .runtime_session_owner_slot_mut_for_owner(owner)? .loaded_page_mut() .ok_or_else(|| "NoDocumentLoaded".to_owned())?; page.fail_pending_subresource_auth_async(internal_id, error_text) @@ -2189,24 +2183,19 @@ impl CdpConnection { internal_id: u64, error_text: String, ) -> Result, String> { - self.fail_pending_subresource_fetch_for_route_async( - session_id, - None, - internal_id, - error_text, - ) - .await + let owner = CommandOwnerScope::capture(self, session_id); + self.fail_pending_subresource_fetch_for_owner_async(&owner, internal_id, error_text) + .await } - pub(crate) async fn fail_pending_subresource_fetch_for_route_async( + pub(crate) async fn fail_pending_subresource_fetch_for_owner_async( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, internal_id: u64, error_text: String, ) -> Result, String> { let page = self - .runtime_session_owner_slot_mut_for_route(session_id, owner_route)? + .runtime_session_owner_slot_mut_for_owner(owner)? .loaded_page_mut() .ok_or_else(|| "NoDocumentLoaded".to_owned())?; page.fail_pending_subresource_fetch_async(internal_id, error_text) @@ -2275,9 +2264,9 @@ impl CdpConnection { response_code: Option, response_headers: Option>, ) -> Result<(), String> { - self.continue_pending_subresource_response_for_route_async( - session_id, - None, + let owner = CommandOwnerScope::capture(self, session_id); + self.continue_pending_subresource_response_for_owner_async( + &owner, internal_id, response_code, response_headers, @@ -2285,16 +2274,15 @@ impl CdpConnection { .await } - pub(crate) async fn continue_pending_subresource_response_for_route_async( + pub(crate) async fn continue_pending_subresource_response_for_owner_async( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, internal_id: u64, response_code: Option, response_headers: Option>, ) -> Result<(), String> { let page = self - .runtime_session_owner_slot_mut_for_route(session_id, owner_route)? + .runtime_session_owner_slot_mut_for_owner(owner)? .loaded_page_mut() .ok_or_else(|| "NoDocumentLoaded".to_owned())?; page.continue_pending_subresource_response_async( @@ -2325,24 +2313,19 @@ impl CdpConnection { internal_id: u64, error_text: String, ) -> Result, String> { - self.fail_pending_subresource_response_for_route_async( - session_id, - None, - internal_id, - error_text, - ) - .await + let owner = CommandOwnerScope::capture(self, session_id); + self.fail_pending_subresource_response_for_owner_async(&owner, internal_id, error_text) + .await } - pub(crate) async fn fail_pending_subresource_response_for_route_async( + pub(crate) async fn fail_pending_subresource_response_for_owner_async( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, internal_id: u64, error_text: String, ) -> Result, String> { let page = self - .runtime_session_owner_slot_mut_for_route(session_id, owner_route)? + .runtime_session_owner_slot_mut_for_owner(owner)? .loaded_page_mut() .ok_or_else(|| "NoDocumentLoaded".to_owned())?; page.fail_pending_subresource_response_async(internal_id, error_text) diff --git a/moli-protocol/src/conn/inspector_route.rs b/moli-protocol/src/conn/inspector_route.rs index 331e0ff5bb..57bd22beed 100644 --- a/moli-protocol/src/conn/inspector_route.rs +++ b/moli-protocol/src/conn/inspector_route.rs @@ -25,7 +25,7 @@ impl CdpConnection { &self, owner: &CommandOwnerScope, ) -> Option { - self.runtime_session_owner_slot_for_route(owner.session_id(), owner.session_owner_route()) + self.runtime_session_owner_slot_for_owner(owner) .ok() .and_then(|slot| slot.current_renderer_attachment()) .map(RendererAgentAttachment::id) @@ -53,12 +53,9 @@ impl CdpConnection { agent_token: RendererDevToolsAgentToken, ) -> Result { self.validate_navigation_target_owner_for_scope(owner, token)?; - self.runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - )? - .prepare_renderer_agent_candidate_token(token, agent_token) - .map_err(|error| error.to_string()) + self.runtime_session_owner_slot_mut_for_owner(owner)? + .prepare_renderer_agent_candidate_token(token, agent_token) + .map_err(|error| error.to_string()) } pub(crate) fn route_current_renderer_inspector_output_for_owner( @@ -67,13 +64,12 @@ impl CdpConnection { batches: Vec, ) -> Vec { let session_id = owner.session_id(); - let owner_route = owner.session_owner_route(); let mut batches = self.filter_renderer_inspector_batches_for_target_owner(owner, batches); if batches.is_empty() { return Vec::new(); } let current_attachment = self - .runtime_session_owner_slot_for_route(session_id, owner_route) + .runtime_session_owner_slot_for_owner(owner) .ok() .and_then(|slot| slot.current_renderer_attachment()); if let Some(current_attachment) = current_attachment { @@ -120,26 +116,23 @@ impl CdpConnection { }) .collect::>(); match self - .runtime_session_owner_slot_mut_for_route(session_id, owner_route) + .runtime_session_owner_slot_mut_for_owner(owner) .and_then(|slot| { slot.route_current_renderer_inspector_output(attachment_id, batches) .map_err(|error| error.to_string()) }) { Ok(batches) => { - let primary_session_id = self - .runtime_session_owner_primary_session_id_for_route(session_id, owner_route); + let primary_session_id = + self.runtime_session_owner_primary_session_id_for_owner(owner); for (session, state) in state_updates { let state_session_id = match &session { DevToolsSessionKey::Primary => primary_session_id.as_deref(), DevToolsSessionKey::Attached(session_id) => Some(session_id.as_str()), }; - let state_owner_route = - state_session_id.is_none().then_some(owner_route).flatten(); - let _ = self.merge_v8_inspector_session_state_for_route( - state_session_id, - state_owner_route, - state, - ); + let state_owner = state_session_id + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); + let _ = self.merge_v8_inspector_session_state_for_owner(&state_owner, state); } batches } @@ -162,17 +155,11 @@ impl CdpConnection { ) -> Result { self.validate_navigation_target_owner_for_scope(owner, candidate.navigation())?; let transaction = self - .runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - )? + .runtime_session_owner_slot_mut_for_owner(owner)? .commit_renderer_agent_candidate_transaction(candidate, renderer_page) .map_err(|error| error.to_string())?; let page_owner = self - .pending_target_page_residence_identity_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + .pending_target_page_residence_identity_for_owner(owner) .ok_or_else(|| "NavigationTargetOwnerMissing".to_owned())?; self.bind_renderer_page_output_owner(renderer_page, page_owner); Ok(transaction) @@ -184,12 +171,9 @@ impl CdpConnection { transaction: CommittedRendererAgentAttachment, ) -> Result<(), String> { self.validate_navigation_target_owner_for_scope(owner, transaction.navigation())?; - self.runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - )? - .rollback_committed_renderer_agent_candidate(transaction) - .map_err(|error| error.to_string()) + self.runtime_session_owner_slot_mut_for_owner(owner)? + .rollback_committed_renderer_agent_candidate(transaction) + .map_err(|error| error.to_string()) } pub(crate) fn finish_renderer_document_navigation_for_owner( @@ -204,10 +188,7 @@ impl CdpConnection { return None; } match self - .runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + .runtime_session_owner_slot_mut_for_owner(owner) .and_then(|slot| { slot.finish_renderer_document_navigation(token) .map_err(|error| error.to_string()) @@ -230,8 +211,7 @@ impl CdpConnection { owner: &CommandOwnerScope, batches: Vec, ) -> Vec { - let owner_identity = - self.target_owner_identity_for_route(owner.session_id(), owner.session_owner_route()); + let owner_identity = self.target_owner_identity_for_owner(owner); batches .into_iter() .filter(|batch| match &batch.session { @@ -251,7 +231,7 @@ impl CdpConnection { token: &DocumentNavigationToken, ) -> Result<(), String> { let (_, target_id) = self - .target_owner_identity_for_route(owner.session_id(), owner.session_owner_route()) + .target_owner_identity_for_owner(owner) .ok_or_else(|| "NoDocumentLoaded".to_owned())?; if target_id.as_deref() != Some(token.target_id.as_str()) { return Err("renderer channel navigation target owner mismatch".to_owned()); diff --git a/moli-protocol/src/conn/page_state/fetch_state.rs b/moli-protocol/src/conn/page_state/fetch_state.rs index 89cb9abae9..b219a9a6ea 100644 --- a/moli-protocol/src/conn/page_state/fetch_state.rs +++ b/moli-protocol/src/conn/page_state/fetch_state.rs @@ -1,9 +1,8 @@ use super::super::{BrowserContext, ConnectionNetworkRequestIdAllocator, PageTargetHost}; #[cfg(test)] use super::super::{ - DocumentBodySource, DocumentNavigationToken, NavigationDispatchState, PausedDocumentTransfer, - PendingFetchAuthNavigation, PendingFetchNavigation, PendingSubresourceFetchAuthRequest, - PendingSubresourceFetchRequest, PendingSubresourceFetchResponseRequest, + DocumentBodySource, DocumentNavigationToken, NavigationDispatchState, + PendingSubresourceFetchRequest, }; fn document_navigation_loader_id(sequence: u64) -> String { @@ -72,22 +71,6 @@ impl BrowserContext { self.page_targets.insert(host) } - #[cfg(test)] - pub(crate) fn take_active_target_pending_fetch_state( - &mut self, - ) -> ( - Vec, - Vec, - Vec, - Vec<(String, PendingSubresourceFetchRequest)>, - Vec<(String, PendingSubresourceFetchAuthRequest)>, - Vec<(String, PendingSubresourceFetchResponseRequest)>, - ) { - self.active_page_target_mut() - .fetch_owner - .drain_pending_requests() - } - #[cfg(test)] pub(crate) fn open_pending_fetch_response_body_stream( &mut self, @@ -425,7 +408,10 @@ mod tests { .fetch_owner .has_in_flight_subresource_fetches_for_test() ); - let _ = bc.take_active_target_pending_fetch_state(); + let _ = bc + .active_page_target_mut() + .fetch_owner + .drain_pending_requests(); assert!( !bc.active_page_target() .fetch_owner diff --git a/moli-protocol/src/conn/renderer_command_turn.rs b/moli-protocol/src/conn/renderer_command_turn.rs index 62fe50ab16..8fe3057862 100644 --- a/moli-protocol/src/conn/renderer_command_turn.rs +++ b/moli-protocol/src/conn/renderer_command_turn.rs @@ -18,7 +18,7 @@ impl CdpConnection { owner: &TargetPageResidenceIdentity, completion: CompletedPageCommand, ) -> RendererCommandTurnOutput { - if !self.target_page_residence_identity_is_current_for_session(session_id, owner) { + if !self.target_page_residence_identity_is_current(owner) { return completion.into_output(); } diff --git a/moli-protocol/src/conn/resource_runtime_support.rs b/moli-protocol/src/conn/resource_runtime_support.rs index e07c3147d5..11c3175bef 100644 --- a/moli-protocol/src/conn/resource_runtime_support.rs +++ b/moli-protocol/src/conn/resource_runtime_support.rs @@ -227,15 +227,15 @@ impl CdpConnection { &mut self, session_id: Option<&str>, ) -> Result, String> { - self.start_rebuild_resource_runtime_for_route(session_id, None) + let owner = super::CommandOwnerScope::capture(self, session_id); + self.start_rebuild_resource_runtime_for_owner(&owner) } - pub(crate) fn start_rebuild_resource_runtime_for_route( + pub(crate) fn start_rebuild_resource_runtime_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&super::CdpSessionRoute>, + owner: &super::CommandOwnerScope, ) -> Result, String> { - let load_inputs = self.navigation_load_inputs_for_route(session_id, owner_route); + let load_inputs = self.navigation_load_inputs_for_owner(owner); let navigator_identity = load_inputs .navigator_identity_override .clone() @@ -249,7 +249,7 @@ impl CdpConnection { storage.into_navigation_storage(), ) .map_err(|error| format!("failed to rebuild resource runtime: {error}"))?; - let Some(page) = self.resource_runtime_apply_page_for_route(session_id, owner_route) else { + let Some(page) = self.resource_runtime_apply_page_for_owner(owner) else { return Ok(None); }; page.start_replace_browser_resource_runtime_with_navigator_identity( @@ -271,14 +271,13 @@ impl CdpConnection { ) } - pub(crate) fn finish_rebuild_resource_runtime_for_route( + pub(crate) fn finish_rebuild_resource_runtime_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&super::CdpSessionRoute>, + owner: &super::CommandOwnerScope, completion: CompletedPageCommand, ) -> Result<(), String> { finish_resource_runtime_update_on_current_attachment( - self.resource_runtime_apply_page_for_route(session_id, owner_route), + self.resource_runtime_apply_page_for_owner(owner), completion, ) } @@ -300,13 +299,12 @@ impl CdpConnection { .ok() } - fn resource_runtime_apply_page_for_route( + fn resource_runtime_apply_page_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&super::CdpSessionRoute>, + owner: &super::CommandOwnerScope, ) -> Option<&mut moli_core::page::Page> { if matches!( - session_id.and_then(|session_id| self.session_route(Some(session_id))), + owner.resolve_route(self), Some(super::CdpSessionRoute::Browser) ) { return self @@ -314,7 +312,7 @@ impl CdpConnection { .as_mut() .and_then(|bc| bc.active_page_target_mut().runtime_slot.loaded_page_mut()); } - self.loaded_page_mut_for_target_configuration_for_route(session_id, owner_route) + self.loaded_page_mut_for_target_configuration_for_owner(owner) .ok() } } diff --git a/moli-protocol/src/conn/runtime_eval.rs b/moli-protocol/src/conn/runtime_eval.rs index 172348f630..2b8fb59909 100644 --- a/moli-protocol/src/conn/runtime_eval.rs +++ b/moli-protocol/src/conn/runtime_eval.rs @@ -232,8 +232,7 @@ enum BidiChannelListenerRoute { #[derive(Debug)] pub(crate) struct OwnerRuntimeResponse { command_id: u64, - session_id: Option, - owner_route: Option, + owner: CommandOwnerScope, object_group: Option, message: Value, bidi_channel_listener: Option, @@ -284,13 +283,12 @@ impl OwnerRuntimeResponse { fn from_pending_inspector_await( command_id: u64, entry: PendingInspectorAwait, - owner_route: Option, + owner: &CommandOwnerScope, message: Value, ) -> Self { Self { command_id, - session_id: entry.session_id().map(str::to_owned), - owner_route, + owner: owner.clone(), object_group: entry.object_group().map(str::to_owned), message, bidi_channel_listener: entry.bidi_channel_listener().cloned(), @@ -298,11 +296,11 @@ impl OwnerRuntimeResponse { } fn session_id(&self) -> Option<&str> { - self.session_id.as_deref() + self.owner.session_id() } - fn owner_route(&self) -> Option<&CdpSessionRoute> { - self.owner_route.as_ref() + fn owner(&self) -> &CommandOwnerScope { + &self.owner } fn object_group(&self) -> Option<&str> { @@ -447,6 +445,7 @@ struct CompletedWorkerRuntimeProtocolDispatch { messages: Vec, session_response_predecessor: Option, session_response_succeeded: Option, + pending_session_response: Option, } impl CompletedWorkerRuntimeProtocolDispatch { @@ -455,19 +454,31 @@ impl CompletedWorkerRuntimeProtocolDispatch { messages, session_response_predecessor: None, session_response_succeeded: None, + pending_session_response: None, } } fn devtools_session( completed: moli_core::page::CompletedWorkerRuntimeInspectorCommandDispatch, ) -> Self { - let (messages, predecessor, response_succeeded) = completed.into_parts(); + let (messages, pending_session_response) = completed.into_parts(); Self { messages, - session_response_predecessor: Some(predecessor), - session_response_succeeded: Some(response_succeeded), + session_response_predecessor: None, + session_response_succeeded: None, + pending_session_response: Some(pending_session_response), } } + + async fn wait_for_session_response(&mut self) -> Result<(), String> { + let Some(pending) = self.pending_session_response.take() else { + return Ok(()); + }; + let (predecessor, response_succeeded) = pending.wait().await?; + self.session_response_predecessor = Some(predecessor); + self.session_response_succeeded = Some(response_succeeded); + Ok(()) + } } pub struct CompletedMoliDiagnosticsDispatch { @@ -695,6 +706,10 @@ impl CompletedRuntimeProtocolMessageDispatch { } impl CompletedSharedWorkerRuntimeProtocolMessageDispatch { + pub(crate) async fn wait_for_session_response(&mut self) -> Result<(), String> { + self.dispatch.wait_for_session_response().await + } + pub(crate) fn take_deferred_response_receiver( &mut self, ) -> Option { @@ -715,6 +730,10 @@ impl CompletedSharedWorkerRuntimeProtocolMessageDispatch { } impl CompletedServiceWorkerRuntimeProtocolMessageDispatch { + pub(crate) async fn wait_for_session_response(&mut self) -> Result<(), String> { + self.dispatch.wait_for_session_response().await + } + pub(crate) fn take_deferred_response_receiver( &mut self, ) -> Option { @@ -905,13 +924,9 @@ impl CdpConnection { object_group, ); } - self.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |state| { - state.try_register_pending_inspector_await(cdp_request_id, session_id, object_group) - }, - ) + self.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.try_register_pending_inspector_await(cdp_request_id, session_id, object_group) + }) .unwrap_or(Ok(())) } @@ -970,17 +985,9 @@ impl CdpConnection { descriptor, ); } - self.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |state| { - state.try_register_renderer_call( - cdp_request_id, - dispatched_attachment_id, - descriptor, - ) - }, - ) + self.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.try_register_renderer_call(cdp_request_id, dispatched_attachment_id, descriptor) + }) .ok_or_else(|| "UnknownSession".to_owned())? .map_err(|error| error.to_string()) } @@ -1017,11 +1024,9 @@ impl CdpConnection { cdp_request_id, ); } - self.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |state| state.take_renderer_call_for_frontend(cdp_request_id), - ) + self.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.take_renderer_call_for_frontend(cdp_request_id) + }) .flatten() } @@ -1075,28 +1080,49 @@ impl CdpConnection { ) } + fn renderer_command_descriptor_for_renderer_if_attachment_matches_for_owner( + &self, + owner: &CommandOwnerScope, + renderer_call_id: RendererCallId, + dispatched_attachment_id: Option, + ) -> Option { + if owner.session_id().is_some() { + return self + .renderer_command_descriptor_for_renderer_if_attachment_matches_for_session_owner( + owner.session_id(), + renderer_call_id, + dispatched_attachment_id, + ); + } + self.target_devtools_session_state_for_owner(owner)? + .renderer_command_descriptor_for_renderer_if_attachment_matches( + renderer_call_id, + dispatched_attachment_id, + ) + } + pub(crate) fn renderer_runtime_command_cause_for_frontend( &self, session_id: Option<&str>, cdp_request_id: u64, ) -> Option { - self.renderer_runtime_command_cause_for_route(session_id, None, cdp_request_id) + let owner = CommandOwnerScope::capture(self, session_id); + self.renderer_runtime_command_cause_for_owner(&owner, cdp_request_id) } - pub(crate) fn renderer_runtime_command_cause_for_route( + pub(crate) fn renderer_runtime_command_cause_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, cdp_request_id: u64, ) -> Option { - let correlation = if session_id.is_some() { - self.renderer_call_for_frontend_for_session_owner(session_id, cdp_request_id) + let correlation = if owner.session_id().is_some() { + self.renderer_call_for_frontend_for_session_owner(owner.session_id(), cdp_request_id) } else { - self.target_devtools_session_state_for_route(session_id, owner_route)? + self.target_devtools_session_state_for_owner(owner)? .renderer_call_for_frontend(cdp_request_id) }?; Some(RendererRuntimeCommandCausalIdentity::new( - self.target_renderer_runtime_inspector_session_id_for_route(session_id, owner_route), + self.target_renderer_runtime_inspector_session_id_for_owner(owner), correlation.renderer_call_id().get(), )) } @@ -1153,17 +1179,13 @@ impl CdpConnection { dispatched_attachment_id, ); } - self.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |state| { - state.take_renderer_call_for_frontend_if_matches( - cdp_request_id, - renderer_call_id, - dispatched_attachment_id, - ) - }, - ) + self.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.take_renderer_call_for_frontend_if_matches( + cdp_request_id, + renderer_call_id, + dispatched_attachment_id, + ) + }) .flatten() } @@ -1180,19 +1202,18 @@ impl CdpConnection { ) == Some(correlation) } - pub(crate) fn take_renderer_call_if_correlation_matches_for_route( + pub(crate) fn take_renderer_call_if_correlation_matches_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, correlation: RendererCommandCorrelation, ) -> bool { - if session_id.is_some() { + if owner.session_id().is_some() { return self.take_renderer_call_if_correlation_matches_for_session_owner( - session_id, + owner.session_id(), correlation, ); } - self.with_target_devtools_session_state_for_route_mut(session_id, owner_route, |state| { + self.with_target_devtools_session_state_for_owner_mut(owner, |state| { state.take_renderer_call_for_frontend_if_matches( correlation.frontend_command_id().get(), correlation.renderer_call_id(), @@ -1250,16 +1271,12 @@ impl CdpConnection { dispatched_attachment_id, ); } - self.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |state| { - state.take_frontend_command_for_renderer_if_attachment_matches( - renderer_call_id, - dispatched_attachment_id, - ) - }, - ) + self.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.take_frontend_command_for_renderer_if_attachment_matches( + renderer_call_id, + dispatched_attachment_id, + ) + }) .flatten() } @@ -1398,7 +1415,7 @@ impl CdpConnection { ); } let owner_target_id = self - .target_owner_identity_for_route(owner.session_id(), owner.session_owner_route()) + .target_owner_identity_for_owner(owner) .and_then(|(_, target_id)| target_id); rewrite_runtime_inspector_command_for_renderer( raw_json, @@ -1415,17 +1432,7 @@ impl CdpConnection { action: &'static str, ) { let session_id = owner.session_id(); - let owner_route = owner - .session_owner_route() - .cloned() - .or_else(|| self.session_route(session_id)); - let job = RuntimeAwaitJob::new( - cdp_request_id, - session_id, - owner_route, - object_group, - action, - ); + let job = RuntimeAwaitJob::new(cdp_request_id, owner, object_group, action); let trace_fields = job.trace_fields(); let key = PendingRendererCommandKey::new(session_id, cdp_request_id); match self.pending_runtime_await_jobs.entry(key) { @@ -1603,18 +1610,14 @@ impl CdpConnection { owner, "BiDi listener residence must be registered under its exact Page owner" ); - let _ = self.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |state| { - state.register_pending_bidi_channel_listener( - cdp_request_id, - owner.session_id(), - Some(BIDI_SCRIPT_RESULT_OBJECT_GROUP), - listener, - ); - }, - ); + let _ = self.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.register_pending_bidi_channel_listener( + cdp_request_id, + owner.session_id(), + Some(BIDI_SCRIPT_RESULT_OBJECT_GROUP), + listener, + ); + }); } pub(crate) fn publish_bidi_channel_listener_start( @@ -1919,11 +1922,9 @@ impl CdpConnection { if owner.session_id().is_some() { return self.remove_pending_inspector_await(cdp_request_id, owner.session_id()); } - self.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |state| state.remove_pending_inspector_await(cdp_request_id), - ) + self.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.remove_pending_inspector_await(cdp_request_id) + }) .flatten() } @@ -2244,11 +2245,9 @@ impl CdpConnection { reason, ); let drained = self - .with_target_devtools_session_state_for_route_mut( - None, - owner.session_owner_route(), - |state| state.drain_pending_inspector_awaits(), - ) + .with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.drain_pending_inspector_awaits() + }) .unwrap_or_default(); for (cdp_id, entry) in drained { self.cancel_runtime_await_job(cdp_id, entry.session_id(), reason); @@ -2267,11 +2266,9 @@ impl CdpConnection { ); } let terminated = self - .with_target_devtools_session_state_for_route_mut( - None, - owner.session_owner_route(), - |state| state.terminate_all_renderer_calls(reason), - ) + .with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.terminate_all_renderer_calls(reason) + }) .unwrap_or_default(); push_terminated_renderer_call_error_background_events(out, terminated, None, reason); } @@ -2360,11 +2357,8 @@ impl CdpConnection { return self .runtime_remote_object_id_known_for_session_owner(owner.session_id(), object_id); } - self.target_devtools_session_state_for_route( - owner.session_id(), - owner.session_owner_route(), - ) - .is_some_and(|state| state.has_runtime_remote_object_id(object_id)) + self.target_devtools_session_state_for_owner(owner) + .is_some_and(|state| state.has_runtime_remote_object_id(object_id)) } pub(crate) fn register_runtime_remote_object_ids_from_value_for_session_owner( @@ -2376,20 +2370,6 @@ impl CdpConnection { self.register_runtime_remote_object_ids_for_session_owner(session_id, object_ids); } - pub(crate) fn register_runtime_remote_object_ids_from_value_for_route( - &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, - value: &Value, - ) { - let object_ids = runtime_remote_object_ids_in_value(value); - let _ = self.with_target_devtools_session_state_for_route_mut( - session_id, - owner_route, - |state| state.register_runtime_remote_object_ids(object_ids), - ); - } - pub(crate) fn register_runtime_remote_object_ids_from_value_for_owner( &mut self, owner: &CommandOwnerScope, @@ -2402,11 +2382,10 @@ impl CdpConnection { ); return; } - self.register_runtime_remote_object_ids_from_value_for_route( - owner.session_id(), - owner.session_owner_route(), - value, - ); + let object_ids = runtime_remote_object_ids_in_value(value); + let _ = self.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.register_runtime_remote_object_ids(object_ids) + }); } pub(crate) fn register_runtime_remote_object_ids_from_value_for_session_owner_with_group( @@ -2423,21 +2402,6 @@ impl CdpConnection { ); } - pub(crate) fn register_runtime_remote_object_ids_from_value_for_route_with_group( - &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, - value: &Value, - object_group: &str, - ) { - let object_ids = runtime_remote_object_ids_in_value(value); - let _ = self.with_target_devtools_session_state_for_route_mut( - session_id, - owner_route, - |state| state.register_runtime_remote_object_ids_with_group(object_ids, object_group), - ); - } - pub(crate) fn register_runtime_remote_object_ids_from_value_for_owner_with_group( &mut self, owner: &CommandOwnerScope, @@ -2452,12 +2416,10 @@ impl CdpConnection { ); return; } - self.register_runtime_remote_object_ids_from_value_for_route_with_group( - owner.session_id(), - owner.session_owner_route(), - value, - object_group, - ); + let object_ids = runtime_remote_object_ids_in_value(value); + let _ = self.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.register_runtime_remote_object_ids_with_group(object_ids, object_group) + }); } pub(crate) fn runtime_remote_object_group_for_session_owner( @@ -2493,12 +2455,9 @@ impl CdpConnection { return self .runtime_remote_object_group_for_session_owner(owner.session_id(), object_id); } - self.target_devtools_session_state_for_route( - owner.session_id(), - owner.session_owner_route(), - )? - .runtime_remote_object_group(object_id) - .map(str::to_owned) + self.target_devtools_session_state_for_owner(owner)? + .runtime_remote_object_group(object_id) + .map(str::to_owned) } pub(crate) fn runtime_remote_object_realm_for_session_owner( @@ -2534,12 +2493,9 @@ impl CdpConnection { return self .runtime_remote_object_realm_for_session_owner(owner.session_id(), object_id); } - self.target_devtools_session_state_for_route( - owner.session_id(), - owner.session_owner_route(), - )? - .runtime_remote_object_realm(object_id) - .map(str::to_owned) + self.target_devtools_session_state_for_owner(owner)? + .runtime_remote_object_realm(object_id) + .map(str::to_owned) } pub(crate) fn runtime_remote_object_alias_for_session_owner( @@ -2575,12 +2531,9 @@ impl CdpConnection { return self .runtime_remote_object_alias_for_session_owner(owner.session_id(), object_id); } - self.target_devtools_session_state_for_route( - owner.session_id(), - owner.session_owner_route(), - )? - .runtime_remote_object_alias(object_id) - .map(str::to_owned) + self.target_devtools_session_state_for_owner(owner)? + .runtime_remote_object_alias(object_id) + .map(str::to_owned) } pub(crate) fn register_runtime_remote_object_alias_for_owner_with_realm( @@ -2599,14 +2552,9 @@ impl CdpConnection { ); return; } - let _ = self.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |state| { - state - .register_runtime_remote_object_alias_with_realm(alias_id, object_id, realm_id); - }, - ); + let _ = self.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.register_runtime_remote_object_alias_with_realm(alias_id, object_id, realm_id); + }); } pub(crate) fn unregister_runtime_remote_object_ids_for_session_owner( @@ -2646,11 +2594,9 @@ impl CdpConnection { ); return; } - let _ = self.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |state| state.unregister_runtime_remote_object_ids(object_ids), - ); + let _ = self.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.unregister_runtime_remote_object_ids(object_ids) + }); } pub(crate) fn unregister_runtime_remote_object_group_for_session_owner( @@ -2687,11 +2633,9 @@ impl CdpConnection { ); return; } - let _ = self.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |state| state.unregister_runtime_remote_object_group(object_group), - ); + let _ = self.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.unregister_runtime_remote_object_group(object_group) + }); } pub(crate) fn clear_runtime_remote_object_tracking_for_session_owner( @@ -2723,9 +2667,8 @@ impl CdpConnection { self.clear_runtime_remote_object_tracking_for_session_owner(owner.session_id()); return; } - let _ = self.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), + let _ = self.with_target_devtools_session_state_for_owner_mut( + owner, DevToolsSessionState::clear_runtime_remote_object_tracking, ); } @@ -2756,9 +2699,8 @@ impl CdpConnection { self.record_runtime_contexts_reported_for_session_owner(owner.session_id()); return; } - let _ = self.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), + let _ = self.with_target_devtools_session_state_for_owner_mut( + owner, DevToolsSessionState::record_runtime_contexts_reported_to_frontend, ); } @@ -2789,9 +2731,8 @@ impl CdpConnection { self.record_runtime_contexts_cleared_for_session_owner(owner.session_id()); return; } - let _ = self.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), + let _ = self.with_target_devtools_session_state_for_owner_mut( + owner, DevToolsSessionState::record_runtime_contexts_cleared_for_frontend, ); } @@ -2877,11 +2818,9 @@ impl CdpConnection { ); return; } - let _ = self.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |state| state.clear_runtime_remote_objects_for_realm(realm_id), - ); + let _ = self.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.clear_runtime_remote_objects_for_realm(realm_id) + }); } pub(crate) fn register_runtime_remote_object_ids_for_session_owner_with_realm( @@ -2935,11 +2874,9 @@ impl CdpConnection { if object_ids.is_empty() { return; } - let _ = self.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |state| state.register_runtime_remote_object_ids_with_realm(object_ids, realm_id), - ); + let _ = self.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.register_runtime_remote_object_ids_with_realm(object_ids, realm_id) + }); } pub(crate) fn register_runtime_remote_object_alias_for_session_owner_with_realm( @@ -3098,8 +3035,7 @@ impl CdpConnection { if owner.session_id().is_some() { return self.runtime_remote_object_owner_identity_for_session(owner.session_id()); } - let (browser_context_id, target_id) = - self.target_owner_identity_for_route(owner.session_id(), owner.session_owner_route())?; + let (browser_context_id, target_id) = self.target_owner_identity_for_owner(owner)?; Some(RuntimeRemoteObjectOwnerIdentity::Page { browser_context_id, target_id, @@ -3386,11 +3322,7 @@ impl CdpConnection { if output.renderer_agent_attachment_id().is_some() && let Some(state) = output.v8_state_update().cloned() { - let _ = self.merge_v8_inspector_session_state_for_route( - owner.session_id(), - owner.session_owner_route(), - state, - ); + let _ = self.merge_v8_inspector_session_state_for_owner(owner, state); } let mut current_seen = false; for message in output.into_messages() { @@ -3452,15 +3384,8 @@ impl CdpConnection { Some(id) => { let entry = self.remove_pending_inspector_await_for_owner(id, owner); if let Some(entry) = entry { - let owner_route = owner - .session_owner_route() - .cloned() - .or_else(|| self.runtime_await_owner_route_for_session(entry.session_id())); let response = OwnerRuntimeResponse::from_pending_inspector_await( - id, - entry, - owner_route, - message, + id, entry, owner, message, ); return self.route_owner_runtime_response_into( response, @@ -3521,11 +3446,10 @@ impl CdpConnection { .into_iter() .map(str::to_owned) .collect::>(); - crate::domains::page::emit_page_window_open_background_events_for_route( + crate::domains::page::emit_page_window_open_background_events_for_owner( self, background_events, - owner.session_id(), - owner.session_owner_route(), + owner, url, window_name, &window_features, @@ -3758,73 +3682,22 @@ impl CdpConnection { } } - /// Resolves terminal responses carried by the renderer's concrete - /// DevTools session output stream. + /// Resolves terminal responses carried by a concrete renderer DevTools + /// session stream. /// - /// Notifications have no renderer call id and remain in place. A response - /// without an exact `(session, attachment, renderer call)` registration is - /// stale and must not expose the renderer-private id on the wire. - pub(crate) fn restore_frontend_command_ids_in_devtools_session_output( + /// The command owner, renderer call id, and attachment id form the complete + /// response authority. Document observations are validated separately, so + /// a response that won its lease immediately before a navigation can still + /// settle the session without granting the retired document permission to + /// publish notifications or mutate replacement-document state. + pub(crate) fn restore_frontend_command_ids_in_devtools_session_output_for_owner( &mut self, - session_id: Option<&str>, - dispatched_attachment_id: RendererAgentAttachmentId, - messages: &mut Vec, - ) { - self.restore_frontend_command_ids_in_devtools_session_output_with_projection( - session_id, - Some(dispatched_attachment_id), - messages, - true, - ); - } - - /// Resolves terminal responses carried by a Worker target's concrete - /// renderer output stream. Worker Inspector sessions do not use a Page - /// attachment id; the exact worker session lifetime is validated by the - /// prepared-output authority at the same ingress boundary. - pub(crate) fn restore_frontend_command_ids_in_worker_devtools_session_output( - &mut self, - session_id: &str, - messages: &mut Vec, - ) { - self.restore_frontend_command_ids_in_devtools_session_output_with_projection( - Some(session_id), - None, - messages, - true, - ); - } - - /// Resolves a terminal response which won its renderer response lease - /// before navigation, but whose old Page journal reached protocol ingress - /// after the replacement attachment committed. - /// - /// The exact `(session, renderer call, attachment)` correlation remains - /// the terminal authority in this race. Notifications and V8 state from - /// the retired attachment are discarded by the caller, and remote-object - /// ownership is intentionally not projected onto the replacement - /// document. - pub(crate) fn restore_frontend_command_ids_in_retired_devtools_session_output( - &mut self, - session_id: Option<&str>, - dispatched_attachment_id: RendererAgentAttachmentId, - messages: &mut Vec, - ) { - self.restore_frontend_command_ids_in_devtools_session_output_with_projection( - session_id, - Some(dispatched_attachment_id), - messages, - false, - ); - } - - fn restore_frontend_command_ids_in_devtools_session_output_with_projection( - &mut self, - session_id: Option<&str>, + owner: &CommandOwnerScope, dispatched_attachment_id: Option, messages: &mut Vec, project_runtime_object_ownership: bool, ) { + let session_id = owner.session_id().map(str::to_owned); messages.retain_mut(|message| { let RendererRuntimeInspectorMessage::Protocol(message) = message else { return true; @@ -3833,46 +3706,50 @@ impl CdpConnection { return true; }; let descriptor = self - .renderer_command_descriptor_for_renderer_if_attachment_matches_for_session_owner( - session_id, + .renderer_command_descriptor_for_renderer_if_attachment_matches_for_owner( + owner, renderer_call_id, dispatched_attachment_id, ); let result_object_group = descriptor.as_ref().and_then(|descriptor| { self.runtime_result_object_group_for_renderer_command_descriptor( - session_id, descriptor, + session_id.as_deref(), + descriptor, ) }); let Some(correlation) = self - .take_frontend_command_for_renderer_if_attachment_matches_for_session_owner( - session_id, + .take_frontend_command_for_renderer_if_attachment_matches_for_owner( + owner, renderer_call_id, dispatched_attachment_id, ) else { tracing::debug!( - session_id, + session_id = session_id.as_deref(), renderer_call_id = renderer_call_id.get(), attachment_id = ?dispatched_attachment_id.map(RendererAgentAttachmentId::get), "dropping DevTools session response without a live renderer correlation" ); return false; }; - message.value_mut()["id"] = json!(correlation.frontend_command_id().get()); + let frontend_command_id = correlation.frontend_command_id().get(); + message.value_mut()["id"] = json!(frontend_command_id); if project_runtime_object_ownership && message.value().get("result").is_some() { if let Some(object_group) = result_object_group.as_deref() { - self.register_runtime_remote_object_ids_from_value_for_session_owner_with_group( - session_id, + self.register_runtime_remote_object_ids_from_value_for_owner_with_group( + owner, message.value(), object_group, ); } else { - self.register_runtime_remote_object_ids_from_value_for_session_owner( - session_id, + self.register_runtime_remote_object_ids_from_value_for_owner( + owner, message.value(), ); } } + self.complete_runtime_await_job(frontend_command_id, session_id.as_deref()); + let _ = self.remove_pending_inspector_await_for_owner(frontend_command_id, owner); true }); } @@ -3986,16 +3863,14 @@ impl CdpConnection { } let routed_session_id = response.session_id().map(str::to_owned); if let Some(object_group) = response.object_group() { - self.register_runtime_remote_object_ids_from_value_for_route_with_group( - routed_session_id.as_deref(), - response.owner_route(), + self.register_runtime_remote_object_ids_from_value_for_owner_with_group( + response.owner(), &response.message, object_group, ); } else { - self.register_runtime_remote_object_ids_from_value_for_route( - routed_session_id.as_deref(), - response.owner_route(), + self.register_runtime_remote_object_ids_from_value_for_owner( + response.owner(), &response.message, ); } @@ -4011,11 +3886,12 @@ impl CdpConnection { fn trace_owner_runtime_response_route(&mut self, response: &OwnerRuntimeResponse) { let current_route = self.runtime_await_owner_route_for_session(response.session_id()); - if current_route != response.owner_route { + let response_owner_route = response.owner().resolve_route(self); + if current_route != response_owner_route { tracing::debug!( command_id = response.command_id, session_id = response.session_id(), - response_owner_route = ?response.owner_route(), + ?response_owner_route, current_owner_route = ?current_route, "owner runtime response route no longer matches current session owner" ); @@ -4025,7 +3901,7 @@ impl CdpConnection { Some(response.command_id), response.session_id(), json!({ - "ownerRoute": response.owner_route().map(|route| format!("{route:?}")), + "ownerRoute": response_owner_route.as_ref().map(|route| format!("{route:?}")), "currentOwnerRoute": current_route.as_ref().map(|route| format!("{route:?}")), }), ); @@ -4112,15 +3988,10 @@ impl CdpConnection { depth: i32, pierce: bool, ) -> Result, String> { - let include_whitespace = crate::domains::dom::dom_agent_includes_whitespace_for_route( - self, - owner.session_id(), - owner.session_owner_route(), - ); - let inspector_session_id = self.target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let include_whitespace = + crate::domains::dom::dom_agent_includes_whitespace_for_owner(self, owner); + let inspector_session_id = + self.target_renderer_runtime_inspector_session_id_for_owner(owner); let pending = { let page = self.runtime_session_owner_page_mut_for_owner(owner)?; page.start_document_node_snapshot_for_object_id_in_inspector_session( @@ -4162,27 +4033,14 @@ impl CdpConnection { .map_err(|error| format!("resolve backend node snapshot failed: {error}")) } - pub(crate) async fn register_document_bidi_node_binding_for_session_owner_async( - &mut self, - session_id: Option<&str>, - shared_id: &str, - backend_node_id: u32, - ) -> Result<(), String> { - let owner = CommandOwnerScope::capture(self, session_id); - self.register_document_bidi_node_binding_for_owner_async(&owner, shared_id, backend_node_id) - .await - } - pub(crate) async fn register_document_bidi_node_binding_for_owner_async( &mut self, owner: &CommandOwnerScope, shared_id: &str, backend_node_id: u32, ) -> Result<(), String> { - let inspector_session_id = self.target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let inspector_session_id = + self.target_renderer_runtime_inspector_session_id_for_owner(owner); let pending = { let page = self.runtime_session_owner_page_mut_for_owner(owner)?; page.start_register_document_bidi_node_binding( @@ -4206,10 +4064,8 @@ impl CdpConnection { owner: &CommandOwnerScope, shared_id: &str, ) -> Result { - let inspector_session_id = self.target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let inspector_session_id = + self.target_renderer_runtime_inspector_session_id_for_owner(owner); let pending = { let page = self.runtime_session_owner_page_mut_for_owner(owner)?; page.start_document_bidi_node_binding(inspector_session_id, shared_id.to_owned()) @@ -4224,15 +4080,15 @@ impl CdpConnection { .map_err(|error| format!("resolve BiDi node binding failed: {error}")) } - pub(crate) async fn document_bidi_node_shared_id_for_backend_node_id_for_session_owner_async( + pub(crate) async fn document_bidi_node_shared_id_for_backend_node_id_for_owner_async( &mut self, - session_id: Option<&str>, + owner: &CommandOwnerScope, backend_node_id: u32, ) -> Result { let inspector_session_id = - self.target_renderer_runtime_inspector_session_id_for_session(session_id); + self.target_renderer_runtime_inspector_session_id_for_owner(owner); let pending = { - let page = self.runtime_session_owner_page_mut(session_id)?; + let page = self.runtime_session_owner_page_mut_for_owner(owner)?; page.start_document_bidi_node_shared_id_for_backend_node_id( inspector_session_id, backend_node_id, @@ -4243,7 +4099,7 @@ impl CdpConnection { .wait() .await .map_err(|error| format!("resolve BiDi node shared id failed: {error}"))?; - let page = self.runtime_session_owner_page_mut(session_id)?; + let page = self.runtime_session_owner_page_mut_for_owner(owner)?; page.finish_document_bidi_node_shared_id_for_backend_node_id(completion) .map_err(|error| format!("resolve BiDi node shared id failed: {error}")) } @@ -4255,10 +4111,8 @@ impl CdpConnection { execution_context_id: Option, object_group: Option<&str>, ) -> Result, String> { - let inspector_session_id = self.target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let inspector_session_id = + self.target_renderer_runtime_inspector_session_id_for_owner(owner); let pending = { let page = self.runtime_session_owner_page_mut_for_owner(owner)?; page.start_resolve_runtime_object_for_backend_node_id_in_inspector_session( @@ -4362,10 +4216,8 @@ impl CdpConnection { owner: &CommandOwnerScope, ) -> Result { let route = self.runtime_protocol_message_page_route_for_owner(owner)?; - let inspector_session_id = self.target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let inspector_session_id = + self.target_renderer_runtime_inspector_session_id_for_owner(owner); let page = self.runtime_session_owner_page_mut_for_owner(owner)?; let pending = page .start_runtime_enable_events_for_inspector_session(inspector_session_id.as_deref()) @@ -4394,21 +4246,14 @@ impl CdpConnection { ); } if let Some(state) = v8_state_update - && !self.merge_v8_inspector_session_state_for_route( - owner.session_id(), - owner.session_owner_route(), - state, - ) + && !self.merge_v8_inspector_session_state_for_owner(&owner, state) { return Err("Runtime.enable completed after session owner disappeared".to_owned()); } let mut replay = RuntimeEnableEventsReplay::from_renderer_messages(messages); let _ = self.set_renderer_runtime_agent_owns_page_console_api_events_for_owner(&owner, true); - self.ingest_runtime_session_owner_output_updates_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + self.ingest_runtime_session_owner_output_updates_for_owner(&owner); for event in replay.events_mut() { match event { RuntimeEnableReplayEvent::Context(event) => { @@ -4433,20 +4278,14 @@ impl CdpConnection { &mut self, owner: &CommandOwnerScope, ) -> Result<&mut Page, String> { - self.loaded_page_mut_for_protocol_access_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + self.loaded_page_mut_for_protocol_access_for_owner(owner) } fn runtime_session_owner_page_mut_for_interruptible_control_for_owner( &mut self, owner: &CommandOwnerScope, ) -> Result<&mut Page, String> { - self.loaded_page_mut_for_interruptible_protocol_access_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + self.loaded_page_mut_for_interruptible_protocol_access_for_owner(owner) } fn runtime_protocol_message_page_route_for_session_owner( @@ -4473,12 +4312,9 @@ impl CdpConnection { owner: &CommandOwnerScope, ) -> Result { let (browser_context_id, target_id) = self - .target_owner_identity_for_route(owner.session_id(), owner.session_owner_route()) + .target_owner_identity_for_owner(owner) .ok_or_else(|| "NoDocumentLoaded".to_owned())?; - let slot = self.runtime_session_owner_slot_for_route( - owner.session_id(), - owner.session_owner_route(), - )?; + let slot = self.runtime_session_owner_slot_for_owner(owner)?; let renderer_agent_attachment_id = slot .current_renderer_attachment() .ok_or_else(|| "NoDocumentLoaded".to_owned())? @@ -5045,15 +4881,15 @@ impl CdpConnection { } pub(crate) fn ingest_runtime_session_owner_output_updates(&mut self, session_id: Option<&str>) { - self.ingest_runtime_session_owner_output_updates_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.ingest_runtime_session_owner_output_updates_for_owner(&owner) } - pub(crate) fn ingest_runtime_session_owner_output_updates_for_route( + pub(crate) fn ingest_runtime_session_owner_output_updates_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) { - if let Ok(slot) = self.runtime_session_owner_slot_mut_for_route(session_id, owner_route) { + if let Ok(slot) = self.runtime_session_owner_slot_mut_for_owner(owner) { let _ = slot.ingest_owner_page_observable_output_updates(); } } @@ -5062,38 +4898,27 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> Option { - self.runtime_session_owner_frame_id_for_route(session_id, None) + let owner = CommandOwnerScope::capture(self, session_id); + self.runtime_session_owner_frame_id_for_owner(&owner) } - pub(crate) fn runtime_session_owner_frame_id_for_route( + pub(crate) fn runtime_session_owner_frame_id_for_owner( &self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option { - if let Some((_, target_id)) = self.target_owner_identity_for_route(session_id, owner_route) - && target_id.is_some() - { - return target_id; - } - match session_id { - None => self + match owner.resolve_route(self)? { + CdpSessionRoute::Browser => self .browser_context .as_ref() .and_then(|bc| bc.active_target_id_owned()), - Some(session_id) => match self.session_route(Some(session_id))? { - CdpSessionRoute::Browser => self - .browser_context - .as_ref() - .and_then(|bc| bc.active_target_id_owned()), - CdpSessionRoute::BrowserContext { browser_context_id } => self - .browser_context_by_id(&browser_context_id) - .and_then(|bc| bc.active_target_id_owned()), - CdpSessionRoute::PageTarget { target_id, .. } => Some(target_id), - CdpSessionRoute::TabTarget { .. } - | CdpSessionRoute::SharedWorkerTarget { .. } - | CdpSessionRoute::DedicatedWorkerTarget { .. } - | CdpSessionRoute::ServiceWorkerTarget { .. } => None, - }, + CdpSessionRoute::BrowserContext { browser_context_id } => self + .browser_context_by_id(&browser_context_id) + .and_then(|bc| bc.active_target_id_owned()), + CdpSessionRoute::PageTarget { target_id, .. } => Some(target_id), + CdpSessionRoute::TabTarget { .. } + | CdpSessionRoute::SharedWorkerTarget { .. } + | CdpSessionRoute::DedicatedWorkerTarget { .. } + | CdpSessionRoute::ServiceWorkerTarget { .. } => None, } } @@ -5228,10 +5053,8 @@ impl CdpConnection { ) -> Result { let route = self.runtime_protocol_message_page_route_for_owner(owner)?; let raw_json = self.rewrite_runtime_inspector_command_for_owner(owner, &raw_json, None)?; - let inspector_session_id = self.target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let inspector_session_id = + self.target_renderer_runtime_inspector_session_id_for_owner(owner); let page = match inspector_route { RendererInspectorCommandRoute::MainThread => { self.runtime_session_owner_page_mut_for_owner(owner)? @@ -5303,10 +5126,8 @@ impl CdpConnection { command_id, Some(route.renderer_agent_attachment_id), )?; - let inspector_session_id = self.target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let inspector_session_id = + self.target_renderer_runtime_inspector_session_id_for_owner(owner); let page_result = match inspector_route { RendererInspectorCommandRoute::MainThread => { self.runtime_session_owner_page_mut_for_owner(owner) @@ -5353,10 +5174,8 @@ impl CdpConnection { ) -> Result { let route = self.runtime_protocol_message_page_route_for_owner(owner)?; let raw_json = self.rewrite_runtime_inspector_command_for_owner(owner, &raw_json, None)?; - let inspector_session_id = self.target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let inspector_session_id = + self.target_renderer_runtime_inspector_session_id_for_owner(owner); let page = self.runtime_session_owner_page_mut_for_owner(owner)?; let pending = page .start_runtime_protocol_message_for_inspector_session_with_context_resolution( @@ -5388,10 +5207,8 @@ impl CdpConnection { command_id, Some(route.renderer_agent_attachment_id), )?; - let inspector_session_id = self.target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let inspector_session_id = + self.target_renderer_runtime_inspector_session_id_for_owner(owner); let page = match self.runtime_session_owner_page_mut_for_owner(owner) { Ok(page) => page, Err(error) => { @@ -5831,8 +5648,11 @@ impl CdpConnection { return; }; debug_assert_eq!(resolved, correlation); + let frontend_command_id = resolved.frontend_command_id().get(); + self.complete_runtime_await_job(frontend_command_id, frontend_session_id); + let _ = self.remove_pending_inspector_await(frontend_command_id, frontend_session_id); let mut response = json!({ - "id": resolved.frontend_command_id().get(), + "id": frontend_command_id, "error": { "code": -32000, "message": message, @@ -6260,7 +6080,7 @@ impl CdpConnection { owner: &CommandOwnerScope, ) -> Result, String> { let target_id = self - .target_owner_identity_for_route(owner.session_id(), owner.session_owner_route()) + .target_owner_identity_for_owner(owner) .and_then(|(_, target_id)| target_id); let page = self.runtime_session_owner_page_mut_for_owner(owner)?; let target_id = target_id.as_deref(); @@ -6303,10 +6123,7 @@ impl CdpConnection { owner: &CommandOwnerScope, ) -> Result, String> { let page = self - .runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - )? + .runtime_session_owner_slot_mut_for_owner(owner)? .loaded_page_mut() .ok_or_else(|| "NoDocumentLoaded".to_owned())?; page.default_or_initial_execution_context_id_async() @@ -6321,7 +6138,7 @@ impl CdpConnection { world_name: &str, ) -> Result { let owner_target_id = self - .target_owner_identity_for_route(owner.session_id(), owner.session_owner_route()) + .target_owner_identity_for_owner(owner) .and_then(|(_, target_id)| target_id); let page = self.runtime_session_owner_page_mut_for_owner(owner)?; let result = if let Some(frame_id) = frame_id @@ -6570,18 +6387,11 @@ impl CdpConnection { &mut self, owner: &CommandOwnerScope, ) -> Result { - let stored_runtime_bindings = self.target_runtime_bindings_for_renderer_route( - owner.session_id(), - owner.session_owner_route(), - ); - let session_runtime_bindings = self.target_runtime_bindings_for_current_inspector_route( - owner.session_id(), - owner.session_owner_route(), - ); - let inspector_session_id = self.target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let stored_runtime_bindings = self.target_runtime_bindings_for_renderer_owner(owner); + let session_runtime_bindings = + self.target_runtime_bindings_for_current_inspector_owner(owner); + let inspector_session_id = + self.target_renderer_runtime_inspector_session_id_for_owner(owner); let page = self.runtime_session_owner_page_mut_for_owner(owner)?; let pending = page .start_set_runtime_binding_state( @@ -6610,18 +6420,11 @@ impl CdpConnection { &mut self, owner: &CommandOwnerScope, ) -> Result<(), String> { - let stored_runtime_bindings = self.target_runtime_bindings_for_renderer_route( - owner.session_id(), - owner.session_owner_route(), - ); - let session_runtime_bindings = self.target_runtime_bindings_for_current_inspector_route( - owner.session_id(), - owner.session_owner_route(), - ); - let inspector_session_id = self.target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let stored_runtime_bindings = self.target_runtime_bindings_for_renderer_owner(owner); + let session_runtime_bindings = + self.target_runtime_bindings_for_current_inspector_owner(owner); + let inspector_session_id = + self.target_renderer_runtime_inspector_session_id_for_owner(owner); let page = self.runtime_session_owner_page_mut_for_owner(owner)?; page.set_runtime_binding_state_async( inspector_session_id, @@ -7405,10 +7208,11 @@ mod tests { }; let mut stale_messages = vec![response()]; - conn.restore_frontend_command_ids_in_devtools_session_output( - Some("SID-attachment-race"), - stale_attachment, + conn.restore_frontend_command_ids_in_devtools_session_output_for_owner( + &CommandOwnerScope::for_session("SID-attachment-race"), + Some(stale_attachment), &mut stale_messages, + true, ); assert!( stale_messages.is_empty(), @@ -7421,10 +7225,11 @@ mod tests { ); let mut live_messages = vec![response()]; - conn.restore_frontend_command_ids_in_devtools_session_output( - Some("SID-attachment-race"), - live_attachment, + conn.restore_frontend_command_ids_in_devtools_session_output_for_owner( + &CommandOwnerScope::for_session("SID-attachment-race"), + Some(live_attachment), &mut live_messages, + true, ); let [RendererRuntimeInspectorMessage::Protocol(message)] = live_messages.as_slice() else { panic!("the live attachment must publish exactly one response"); @@ -7464,10 +7269,11 @@ mod tests { })), ]; - conn.restore_frontend_command_ids_in_devtools_session_output( - Some("SID-duplicate-response"), - attachment_id, + conn.restore_frontend_command_ids_in_devtools_session_output_for_owner( + &CommandOwnerScope::for_session("SID-duplicate-response"), + Some(attachment_id), &mut messages, + true, ); let [RendererRuntimeInspectorMessage::Protocol(message)] = messages.as_slice() else { @@ -7515,10 +7321,11 @@ mod tests { })), ]; - conn.restore_frontend_command_ids_in_devtools_session_output( - Some("SID-interleaved-response"), - attachment_id, + conn.restore_frontend_command_ids_in_devtools_session_output_for_owner( + &CommandOwnerScope::for_session("SID-interleaved-response"), + Some(attachment_id), &mut messages, + true, ); assert_eq!(messages.len(), 3); @@ -7590,10 +7397,11 @@ mod tests { })), ]; - conn.restore_frontend_command_ids_in_devtools_session_output( - Some("SID-session-output"), - attachment_id, + conn.restore_frontend_command_ids_in_devtools_session_output_for_owner( + &CommandOwnerScope::for_session("SID-session-output"), + Some(attachment_id), &mut messages, + true, ); assert_eq!( @@ -7667,10 +7475,11 @@ mod tests { }] }, }))]; - conn.restore_frontend_command_ids_in_devtools_session_output( - session_id, - attachment_id, + conn.restore_frontend_command_ids_in_devtools_session_output_for_owner( + &CommandOwnerScope::for_session("SID-session-projection"), + Some(attachment_id), &mut messages, + true, ); assert_eq!( conn.runtime_remote_object_group_for_session_owner(session_id, "nested-child-object",), diff --git a/moli-protocol/src/conn/runtime_load.rs b/moli-protocol/src/conn/runtime_load.rs index c4c5b16dca..aac7569ab2 100644 --- a/moli-protocol/src/conn/runtime_load.rs +++ b/moli-protocol/src/conn/runtime_load.rs @@ -1547,10 +1547,7 @@ impl CdpConnection { navigation: &NavigationDispatchState, ) -> TargetNavigationLoadInputs { apply_navigation_request_load_policy( - self.navigation_load_inputs_for_route( - navigation.owner.session_id(), - navigation.owner.session_owner_route(), - ), + self.navigation_load_inputs_for_owner(&navigation.owner), navigation.request_load_policy, ) .with_main_document_commit_seed(RendererMainDocumentCommitSeed::from_navigation(navigation)) @@ -1562,8 +1559,7 @@ impl CdpConnection { final_url: &Url, ) -> Result { let idle_override = self.idle_override_for_navigation(owner, final_url); - let load_inputs = - self.navigation_load_inputs_for_route(owner.session_id(), owner.session_owner_route()); + let load_inputs = self.navigation_load_inputs_for_owner(owner); // The renderer runtime is shared by the BrowserContext, but each Page // target owns its NavigationEngine and may have a different transport // identity. Resolve through that target's engine at the commit @@ -1616,7 +1612,7 @@ impl CdpConnection { // navigation can retain that frame-host state; a cross-site renderer // replacement must start with the actual idle state. let page = self - .runtime_session_owner_slot_for_route(owner.session_id(), owner.session_owner_route()) + .runtime_session_owner_slot_for_owner(owner) .ok()? .loaded_page()?; moli_site::same_site_urls(page.final_url(), final_url, true) @@ -1695,12 +1691,8 @@ impl CdpConnection { let main_document_commit = load_inputs .main_document_commit_for_final_url(&final_url, None) .map(Arc::new); - let page_reservation = self.reserve_renderer_page_for_route( - navigation.owner.session_id(), - navigation.owner.session_owner_route(), - &load_inputs, - &engine, - ); + let page_reservation = + self.reserve_renderer_page_for_owner(&navigation.owner, &load_inputs, &engine); let prepared_page = engine .prepare_streaming_raw_page_from_external_body_with_storage_and_inspector_session_restores_async( page_reservation, @@ -1785,9 +1777,7 @@ impl CdpConnection { &mut self, owner: &CommandOwnerScope, ) -> Result, String> { - let runtime_slot = match self - .runtime_session_owner_slot_for_route(owner.session_id(), owner.session_owner_route()) - { + let runtime_slot = match self.runtime_session_owner_slot_for_owner(owner) { Ok(slot) => slot, Err(_) => return Ok(None), }; @@ -1805,10 +1795,7 @@ impl CdpConnection { // it, while rejecting the ensure would incorrectly reject attachment. // Treat this as an already-satisfied ensure and let the exact // target-owned navigation install the replacement Document. - if self.has_pending_document_navigation_for_route( - owner.session_id(), - owner.session_owner_route(), - ) { + if self.has_pending_document_navigation_for_owner(owner) { return Ok(None); } @@ -1827,22 +1814,16 @@ impl CdpConnection { &self, owner: &CommandOwnerScope, ) -> bool { - if let Some(is_on_initial_empty_document) = self - .runtime_session_owner_record_is_on_initial_empty_document_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + if let Some(is_on_initial_empty_document) = + self.runtime_session_owner_record_is_on_initial_empty_document_for_owner(owner) { return is_on_initial_empty_document; } - self.runtime_session_owner_target_url_for_route( - owner.session_id(), - owner.session_owner_route(), - ) - .as_deref() - .and_then(|raw_url| Url::parse(raw_url).ok()) - .as_ref() - .is_some_and(moli_url::is_about_blank) + self.runtime_session_owner_target_url_for_owner(owner) + .as_deref() + .and_then(|raw_url| Url::parse(raw_url).ok()) + .as_ref() + .is_some_and(moli_url::is_about_blank) } /// Returns whether the materialized initial `about:blank` still needs to @@ -1851,16 +1832,16 @@ impl CdpConnection { /// This is a structural lifecycle query. It deliberately does not look /// at `waitForDebuggerOnStart`: the explicit debugger-resume path uses it /// after the paused session has been released. - pub(crate) fn runtime_session_owner_needs_initial_document_navigation( + pub(crate) fn runtime_session_owner_needs_initial_document_navigation_for_owner( &self, - session_id: Option<&str>, + owner: &CommandOwnerScope, ) -> bool { - if !self.runtime_session_owner_initial_empty_document_has_replacement_url(session_id) { + if !self.runtime_session_owner_initial_empty_document_has_replacement_url_for_owner(owner) { return false; } - if self.runtime_session_owner_initial_empty_document_has_pending_cross_document_navigation( - session_id, - ) { + if self + .runtime_session_owner_initial_empty_document_has_pending_cross_document_navigation_for_owner(owner) + { return false; } true @@ -1878,22 +1859,38 @@ impl CdpConnection { &self, session_id: Option<&str>, ) -> bool { - !self.session_owner_target_has_waiting_for_debugger_session(session_id) - && self.runtime_session_owner_needs_initial_document_navigation(session_id) + let owner = CommandOwnerScope::capture(self, session_id); + self.runtime_session_owner_can_start_initial_document_navigation_for_owner(&owner) + } + + pub(crate) fn runtime_session_owner_can_start_initial_document_navigation_for_owner( + &self, + owner: &CommandOwnerScope, + ) -> bool { + !self.owner_target_has_waiting_for_debugger_session(owner) + && self.runtime_session_owner_needs_initial_document_navigation_for_owner(owner) } pub(crate) fn runtime_session_owner_initial_empty_document_has_replacement_url( &self, session_id: Option<&str>, ) -> bool { - if !self.runtime_session_owner_target_is_initial_about_blank(session_id) { + let owner = CommandOwnerScope::capture(self, session_id); + self.runtime_session_owner_initial_empty_document_has_replacement_url_for_owner(&owner) + } + + pub(crate) fn runtime_session_owner_initial_empty_document_has_replacement_url_for_owner( + &self, + owner: &CommandOwnerScope, + ) -> bool { + if !self.runtime_session_owner_target_is_initial_about_blank_for_owner(owner) { return false; } - let Some(target_url) = self.runtime_session_owner_target_url(session_id) else { + let Some(target_url) = self.runtime_session_owner_target_url_for_owner(owner) else { return false; }; let Some(initial_url) = - self.runtime_session_owner_record_initial_empty_document_url(session_id) + self.runtime_session_owner_record_initial_empty_document_url_for_owner(owner) else { return false; }; @@ -1904,9 +1901,7 @@ impl CdpConnection { &mut self, owner: &CommandOwnerScope, ) -> Result, String> { - let runtime_slot = match self - .runtime_session_owner_slot_for_route(owner.session_id(), owner.session_owner_route()) - { + let runtime_slot = match self.runtime_session_owner_slot_for_owner(owner) { Ok(slot) => slot, Err(_) => return Ok(None), }; @@ -1923,10 +1918,9 @@ impl CdpConnection { } let page_owner = self - .initial_document_page_owner_for_route(owner.session_id(), owner.session_owner_route()) + .initial_document_page_owner_for_owner(owner) .ok_or_else(|| "TargetNotLoaded".to_owned())?; - let load_inputs = - self.navigation_load_inputs_for_route(owner.session_id(), owner.session_owner_route()); + let load_inputs = self.navigation_load_inputs_for_owner(owner); let requested_url = self .runtime_session_owner_initial_empty_document_url_for_owner(owner) .unwrap_or_else(|| Url::parse("about:blank").expect("about:blank should be valid")); @@ -1934,35 +1928,23 @@ impl CdpConnection { load_inputs.fetch_subresource_interception; let mut engine = self.background_navigation_engine_for_load_inputs(&load_inputs); let page_storage = load_inputs.page_storage_handles(); - let top_level_storage_key = self - .runtime_session_owner_initial_empty_document_storage_key_for_route( - owner.session_id(), - owner.session_owner_route(), - ); - self.runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - )? - .start_initial_document_page_build(); + let top_level_storage_key = + self.runtime_session_owner_initial_empty_document_storage_key_for_owner(owner); + self.runtime_session_owner_slot_mut_for_owner(owner)? + .start_initial_document_page_build(); let page_reservation = engine.reserve_page_for_creation(); let renderer_page = RendererPageResidenceIdentity::from_parts( page_reservation.local_host_id(), page_reservation.page_id(), ); if !self - .runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - )? + .runtime_session_owner_slot_mut_for_owner(owner)? .bind_initial_document_page_build_renderer_page(renderer_page) { let message = "initial document Page reservation no longer matches its target build".to_owned(); let _ = self - .runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + .runtime_session_owner_slot_mut_for_owner(owner) .map(|slot| { slot.fail_initial_document_page_build(message.clone()); slot.mark_loaded_page_absent( @@ -1977,10 +1959,7 @@ impl CdpConnection { // command; binding after `start_*` would leave a real cross-thread race // where the concrete FIFO receives its first publication ownerless. let renderer_page_owner = self - .pending_target_page_residence_identity_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + .pending_target_page_residence_identity_for_owner(owner) .ok_or_else(|| "initial document Page reservation lost its target owner".to_owned())?; self.bind_renderer_page_output_owner(renderer_page, renderer_page_owner); let pending = engine @@ -2019,10 +1998,7 @@ impl CdpConnection { .map_err(|error| { let message = format!("failed to start initial document page build: {error}"); let _ = self - .runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + .runtime_session_owner_slot_mut_for_owner(owner) .map(|slot| { slot.fail_initial_document_page_build(message.clone()); slot.mark_loaded_page_absent( @@ -2087,21 +2063,15 @@ impl CdpConnection { &self, owner: &CommandOwnerScope, ) -> Option { - if let Some(raw_url) = self - .runtime_session_owner_record_initial_empty_document_url_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + if let Some(raw_url) = + self.runtime_session_owner_record_initial_empty_document_url_for_owner(owner) { return Url::parse(&raw_url).ok().filter(moli_url::is_about_blank); } - self.runtime_session_owner_target_url_for_route( - owner.session_id(), - owner.session_owner_route(), - ) - .as_deref() - .and_then(|raw_url| Url::parse(raw_url).ok()) - .filter(moli_url::is_about_blank) + self.runtime_session_owner_target_url_for_owner(owner) + .as_deref() + .and_then(|raw_url| Url::parse(raw_url).ok()) + .filter(moli_url::is_about_blank) } fn complete_initial_document_page_build_for_page_owner( @@ -2224,8 +2194,7 @@ impl CdpConnection { raw_url: &str, ) -> Result { let owner = CommandOwnerScope::capture(self, None); - let load_inputs = - self.navigation_load_inputs_for_route(owner.session_id(), owner.session_owner_route()); + let load_inputs = self.navigation_load_inputs_for_owner(&owner); self.load_navigation_via_runtime_with_load_inputs_async(&owner, raw_url, load_inputs) .await } @@ -2328,7 +2297,7 @@ impl CdpConnection { ) -> Result { let owner = CommandOwnerScope::capture(self, session_id); let load_inputs = apply_navigation_request_load_policy( - self.navigation_load_inputs_for_route(owner.session_id(), owner.session_owner_route()), + self.navigation_load_inputs_for_owner(&owner), request_load_policy, ); self.load_navigation_request_via_runtime_with_network_events_and_load_inputs_async( @@ -2484,12 +2453,8 @@ impl CdpConnection { let shared_resource_runtime = self.shared_resource_runtime_for_navigation_load_inputs(&load_inputs); let engine = self.background_navigation_engine_for_load_inputs(&load_inputs); - let page_reservation = self.reserve_renderer_page_for_route( - navigation.owner.session_id(), - navigation.owner.session_owner_route(), - &load_inputs, - &engine, - ); + let page_reservation = + self.reserve_renderer_page_for_owner(&navigation.owner, &load_inputs, &engine); Some(BackgroundNavigationLoadJob { engine, page_reservation, @@ -2535,12 +2500,8 @@ impl CdpConnection { let shared_resource_runtime = self.shared_resource_runtime_for_navigation_load_inputs(&load_inputs); let engine = self.background_navigation_engine_for_load_inputs(&load_inputs); - let page_reservation = self.reserve_renderer_page_for_route( - navigation.owner.session_id(), - navigation.owner.session_owner_route(), - &load_inputs, - &engine, - ); + let page_reservation = + self.reserve_renderer_page_for_owner(&navigation.owner, &load_inputs, &engine); BackgroundStreamingResponseNavigationLoadJob { engine, page_reservation, @@ -2569,36 +2530,15 @@ impl CdpConnection { owner: &CommandOwnerScope, load_inputs: &TargetNavigationLoadInputs, engine: &NavigationEngine, - ) -> RendererPageReservationToken { - self.reserve_renderer_page_for_route( - owner.session_id(), - owner.session_owner_route(), - load_inputs, - engine, - ) - } - - fn reserve_renderer_page_for_route( - &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, - load_inputs: &TargetNavigationLoadInputs, - engine: &NavigationEngine, ) -> RendererPageReservationToken { let page_reservation = engine.reserve_page_for_creation(); - self.bind_renderer_page_reservation_for_route( - session_id, - owner_route, - load_inputs, - page_reservation, - ); + self.bind_renderer_page_reservation_for_owner(owner, load_inputs, page_reservation); page_reservation } - fn bind_renderer_page_reservation_for_route( + fn bind_renderer_page_reservation_for_owner( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, load_inputs: &TargetNavigationLoadInputs, page_reservation: RendererPageReservationToken, ) { @@ -2610,7 +2550,7 @@ impl CdpConnection { // reservation; recording `target_id: None` here would conflict with // that exact owner when the stream-open control is later consumed. if let Some((browser_context_id, Some(_target_id))) = - self.target_owner_identity_for_route(session_id, owner_route) + self.target_owner_identity_for_owner(owner) { assert_eq!( load_inputs.browser_context_id.as_deref(), @@ -2622,11 +2562,7 @@ impl CdpConnection { page_reservation.page_id(), ); let page_owner = self - .reserve_target_page_residence_identity_for_route( - session_id, - owner_route, - renderer_page, - ) + .reserve_target_page_residence_identity_for_owner(owner, renderer_page) .expect("navigation Page reservation must retain its target owner"); self.bind_renderer_page_output_owner(renderer_page, page_owner); } @@ -3183,10 +3119,9 @@ impl CdpConnection { .map_err(|error| format!("failed to fetch page `{raw_url}`: {error}")) } - pub(crate) async fn fetch_navigation_auth_raw_response_for_route_async( + pub(crate) async fn fetch_navigation_auth_raw_response_for_owner_async( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, request_load_policy: NavigationRequestLoadPolicy, method: &str, raw_url: &str, @@ -3195,7 +3130,7 @@ impl CdpConnection { auth: SubresourceAuthCredentials, ) -> Result, String> { let load_inputs = apply_navigation_request_load_policy( - self.navigation_load_inputs_for_route(session_id, owner_route), + self.navigation_load_inputs_for_owner(owner), request_load_policy, ); ensure_url_not_blocked_for_load_inputs(&load_inputs, raw_url)?; @@ -3245,10 +3180,9 @@ impl CdpConnection { .await } - pub(crate) async fn fetch_navigation_streaming_raw_response_for_route_async( + pub(crate) async fn fetch_navigation_streaming_raw_response_for_owner_async( &mut self, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, request_load_policy: NavigationRequestLoadPolicy, method: &str, raw_url: &str, @@ -3257,7 +3191,7 @@ impl CdpConnection { auth: Option, ) -> Result, String> { let load_inputs = apply_navigation_request_load_policy( - self.navigation_load_inputs_for_route(session_id, owner_route), + self.navigation_load_inputs_for_owner(owner), request_load_policy, ); self.fetch_navigation_streaming_raw_response_with_load_inputs_async( @@ -3477,8 +3411,7 @@ impl CdpConnection { response: NetworkFetchResult, ) -> Result { let owner = CommandOwnerScope::capture(self, session_id); - let load_inputs = - self.navigation_load_inputs_for_route(owner.session_id(), owner.session_owner_route()); + let load_inputs = self.navigation_load_inputs_for_owner(&owner); self.build_navigation_from_buffered_raw_response_with_load_inputs_async( &owner, &load_inputs, @@ -3671,8 +3604,7 @@ impl CdpConnection { body_progress_source: MainDocumentBodyProgressSource, ) -> Result { let owner = CommandOwnerScope::capture(self, session_id); - let load_inputs = - self.navigation_load_inputs_for_route(owner.session_id(), owner.session_owner_route()); + let load_inputs = self.navigation_load_inputs_for_owner(&owner); self.build_navigation_from_streaming_raw_response_with_load_inputs_async( &owner, &load_inputs, diff --git a/moli-protocol/src/conn/target/activation.rs b/moli-protocol/src/conn/target/activation.rs index fa68c3e618..2ed07dd00f 100644 --- a/moli-protocol/src/conn/target/activation.rs +++ b/moli-protocol/src/conn/target/activation.rs @@ -1,4 +1,4 @@ -use crate::conn::{BackgroundProtocolEvent, BrowserContext, CdpConnection}; +use crate::conn::{BackgroundProtocolEvent, BrowserContext, CdpConnection, CommandOwnerScope}; /// The stable Target identities on both sides of one foreground selection. #[derive(Clone, Debug, PartialEq, Eq)] @@ -144,10 +144,15 @@ impl CdpConnection { let Some(route) = self.target_session_route_for_target_id(target_id) else { return Vec::new(); }; - self.page_event_session_ids_for_route(None, Some(&route)) + let owner = CommandOwnerScope::for_route(route); + self.page_event_session_ids_for_owner(&owner) .into_iter() .filter(|session_id| { - self.target_page_session_state_for_route(session_id.as_deref(), Some(&route)) + let event_owner = session_id + .as_deref() + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); + self.target_page_session_state_for_owner(&event_owner) .is_some_and(|state| state.page_screencast.is_active()) }) .collect() diff --git a/moli-protocol/src/conn/target/route.rs b/moli-protocol/src/conn/target/route.rs index 5f99e060dc..3bd8f8ca15 100644 --- a/moli-protocol/src/conn/target/route.rs +++ b/moli-protocol/src/conn/target/route.rs @@ -40,6 +40,24 @@ pub(crate) enum CdpSessionRoute { } impl CdpSessionRoute { + pub(crate) fn addresses_same_target_as(&self, other: &Self) -> bool { + match (self, other) { + ( + Self::PageTarget { + browser_context_id: left_context, + target_id: left_target, + .. + }, + Self::PageTarget { + browser_context_id: right_context, + target_id: right_target, + .. + }, + ) => left_context == right_context && left_target == right_target, + _ => self == other, + } + } + pub(crate) fn browser_context_id(&self) -> Option<&str> { match self { Self::Browser => None, @@ -272,43 +290,6 @@ impl CdpConnection { self.browser_contexts() .any(|browser_context| browser_context.has_attached_child_frame_id(frame_id)) } - - #[cfg(test)] - pub(crate) fn has_background_target_session(&self, session_id: Option<&str>) -> bool { - self.background_target_route(session_id).is_some() - } - - #[cfg(test)] - pub(crate) fn background_target_id_for_session( - &self, - session_id: Option<&str>, - ) -> Option { - self.background_target_route(session_id) - .map(|(_, target_id)| target_id) - } - - #[cfg(test)] - pub(crate) fn background_target_route( - &self, - session_id: Option<&str>, - ) -> Option<(String, String)> { - match self.session_route(session_id)? { - CdpSessionRoute::PageTarget { - browser_context_id, - target_id, - .. - } => (!self - .browser_context_by_id(&browser_context_id)? - .is_active_target(&target_id)) - .then_some((browser_context_id, target_id)), - CdpSessionRoute::Browser - | CdpSessionRoute::BrowserContext { .. } - | CdpSessionRoute::TabTarget { .. } - | CdpSessionRoute::SharedWorkerTarget { .. } - | CdpSessionRoute::DedicatedWorkerTarget { .. } - | CdpSessionRoute::ServiceWorkerTarget { .. } => None, - } - } } fn prepared_browser_context_session_route( browser_context: &BrowserContext, @@ -387,8 +368,11 @@ mod tests { assert_eq!(connection.session_route(Some("SID-a")), Some(route)); assert_eq!( - connection.background_target_route(Some("SID-a")), - Some(("BID-route".to_owned(), "TID-a".to_owned())) + connection + .browser_context + .as_ref() + .and_then(BrowserContext::active_target_id), + Some("TID-b") ); } diff --git a/moli-protocol/src/conn/tests/mod.rs b/moli-protocol/src/conn/tests/mod.rs index 6de1458134..86fd078b90 100644 --- a/moli-protocol/src/conn/tests/mod.rs +++ b/moli-protocol/src/conn/tests/mod.rs @@ -435,13 +435,17 @@ fn background_navigation_completion_sender_routes_explicit_session_owners() { conn.set_background_navigation_completion_sender(sender); assert!( - conn.background_navigation_completion_sender_for_route(Some("SID-active"), None) - .is_some(), + conn.background_navigation_completion_sender_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-active") + ) + .is_some(), "a command scoped to a concrete target owner can continue navigation work in the background" ); assert!( - conn.background_navigation_completion_sender_for_route(Some("SID-inactive"), None) - .is_some(), + conn.background_navigation_completion_sender_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-inactive") + ) + .is_some(), "inactive-context target owners should also be routable by explicit session id" ); } diff --git a/moli-protocol/src/conn/top_level_navigation_work.rs b/moli-protocol/src/conn/top_level_navigation_work.rs index e1045ae849..07cca391a1 100644 --- a/moli-protocol/src/conn/top_level_navigation_work.rs +++ b/moli-protocol/src/conn/top_level_navigation_work.rs @@ -1,6 +1,6 @@ use moli_core::page::RendererDocumentSourcedTopLevelLocationNavigation; -use super::{CdpConnection, CommandOwnerScope, TargetPageResidenceIdentity}; +use super::{CommandOwnerScope, TargetPageResidenceIdentity}; /// One renderer-requested top-level navigation projected from a concrete /// renderer output record. @@ -34,13 +34,12 @@ impl TopLevelLocationNavigationOwnerAction { /// concrete action rather than execute the navigation inline or rescan the /// current Page. pub(crate) fn from_prepared( - conn: &CdpConnection, - session_id: Option<&str>, + owner_scope: CommandOwnerScope, page_owner: TargetPageResidenceIdentity, navigation: RendererDocumentSourcedTopLevelLocationNavigation, ) -> Self { Self { - owner_scope: CommandOwnerScope::capture(conn, session_id), + owner_scope, page_owner, navigation, } diff --git a/moli-protocol/src/domains/accessibility.rs b/moli-protocol/src/domains/accessibility.rs index e17e9ee658..9a1429f257 100644 --- a/moli-protocol/src/domains/accessibility.rs +++ b/moli-protocol/src/domains/accessibility.rs @@ -678,16 +678,13 @@ pub(crate) async fn complete_pending_accessibility_command( let CompletedAccessibilityCommandWork::Page(completed) = completed; let completed = *completed; - let session_id = owner_scope.session_id().map(str::to_owned); - let session_id_ref = session_id.as_deref(); - let owner_route = owner_scope.session_owner_route(); - if let Err(message) = conn.ensure_document_accessible_for_route(session_id_ref, owner_route) { + if let Err(message) = conn.ensure_document_accessible_for_owner(&owner_scope) { return AccessibilityCommandDispatchStep::Complete(CommandOutputPlan::error( -32000, message, )); } let Some(page) = conn - .loaded_page_mut_for_protocol_access_for_route(session_id_ref, owner_route) + .loaded_page_mut_for_protocol_access_for_owner(&owner_scope) .ok() else { return AccessibilityCommandDispatchStep::Complete(CommandOutputPlan::error( diff --git a/moli-protocol/src/domains/activity/main_document.rs b/moli-protocol/src/domains/activity/main_document.rs index f6299562f8..ba45bf1e78 100644 --- a/moli-protocol/src/domains/activity/main_document.rs +++ b/moli-protocol/src/domains/activity/main_document.rs @@ -147,10 +147,10 @@ impl MainDocumentNavigationActivity { self.emit_navigation_result_from_state_into_buffer(out); } let mut target_info_events = Vec::new(); - crate::domains::target::emit_target_info_changed_for_session_owner_background_event( + crate::domains::target::emit_target_info_changed_for_owner_background_event( conn, &mut target_info_events, - self.state.owner.session_id(), + &self.state.owner, ); out.extend_background_events_after_messages(target_info_events); if timing_enabled { @@ -313,17 +313,10 @@ impl MainDocumentNavigationActivity { // The document token is the document identity. A same-document // navigation may update the target URL between DCL and load, but // it must not make the current document's load completion stale. - return conn.accepts_document_body_completion_for_route( - self.state.owner.session_id(), - self.state.owner.session_owner_route(), - token, - ); + return conn.accepts_document_body_completion_for_owner(&self.state.owner, token); } - conn.runtime_session_owner_target_url_for_route( - self.state.owner.session_id(), - self.state.owner.session_owner_route(), - ) - .is_some_and(|url| url == self.final_url.as_str()) + conn.runtime_session_owner_target_url_for_owner(&self.state.owner) + .is_some_and(|url| url == self.final_url.as_str()) } async fn emit_download_navigation_commit_into_buffer_async( @@ -581,7 +574,7 @@ impl MainDocumentNavigationActivity { let error = conn .handle_pending_download_activation_inline_async( &mut download_events, - self.state.owner.session_id(), + &self.state.owner, download, &mut command_context, ) @@ -672,12 +665,7 @@ impl DeferredMainDocumentLoadCompletionAdmission { ) -> DeferredMainDocumentLoadCompletionActivity { let is_current = self.is_still_current_for_scheduler(conn); let renderer_page_residence_identity = is_current - .then(|| { - conn.renderer_page_residence_identity_for_route( - self.owner_scope().session_id(), - self.owner_scope().session_owner_route(), - ) - }) + .then(|| conn.renderer_page_residence_identity_for_owner(self.owner_scope())) .flatten(); let lifecycle_observer = if is_current { conn.register_exact_renderer_document_lifecycle_observer_for_owner( @@ -1622,8 +1610,11 @@ mod tests { Some(&binding), RendererDocumentLifecycleMilestone::Load, ); - conn.start_document_navigation_for_route(Some("SID-nav"), None, "LID-2".to_owned()) - .expect("replacement navigation token"); + conn.start_document_navigation_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-nav"), + "LID-2".to_owned(), + ) + .expect("replacement navigation token"); assert_eq!( observer.wait().await, @@ -1654,8 +1645,11 @@ mod tests { conn.enqueue_deferred_main_document_load_completion(old_completion); let work = take_deferred_load_work_for_test(&mut conn); - conn.start_document_navigation_for_route(Some("SID-nav"), None, "LID-2".to_owned()) - .expect("replacement navigation token"); + conn.start_document_navigation_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-nav"), + "LID-2".to_owned(), + ) + .expect("replacement navigation token"); assert!( conn.take_scheduler_events().is_empty(), diff --git a/moli-protocol/src/domains/activity/output_ingress/prepared_outputs.rs b/moli-protocol/src/domains/activity/output_ingress/prepared_outputs.rs index 1897f9e956..831db52169 100644 --- a/moli-protocol/src/domains/activity/output_ingress/prepared_outputs.rs +++ b/moli-protocol/src/domains/activity/output_ingress/prepared_outputs.rs @@ -47,11 +47,9 @@ impl PreparedProtocolOutputs { source_document: moli_core::RendererDocumentLifecycleIdentity, item: &moli_core::page::ScriptNetworkOutputItem, ) -> Option { - let session_id = owner.session_id(); let renderer_live = conn - .ingest_renderer_page_network_output_item_and_prepare_live_delivery_for_route( - session_id, - owner.session_owner_route(), + .ingest_renderer_page_network_output_item_and_prepare_live_delivery_for_owner( + owner, source_renderer_page, source_document, item, @@ -138,26 +136,11 @@ impl PreparedProtocolOutputs { .append_to_output_sink(&mut prepared); return prepared; } - let source_batches = vec![batch.clone()]; - let batches = conn.route_current_renderer_inspector_output_for_owner( - owner, - source_batches.clone(), - ); - if batches.is_empty() { - crate::domains::runtime::RuntimePreparedOutputs:: - from_retired_renderer_runtime_inspector_session_responses( - conn, - owner, - &source_batches, - ) - .append_to_output_sink(&mut prepared); - return prepared; - } crate::domains::runtime::RuntimePreparedOutputs:: - from_renderer_runtime_inspector_message_batches( + from_page_renderer_runtime_inspector_message_batches( conn, owner, - &batches, + vec![batch.clone()], ) .append_to_output_sink(&mut prepared); } @@ -219,7 +202,6 @@ impl PreparedProtocolOutputs { owner: &CommandOwnerScope, action: RendererOwnerAction, ) -> Self { - let session_id = owner.session_id(); let mut prepared = Self::empty(); match action { RendererOwnerAction::FileChooser(activation) => { @@ -360,9 +342,7 @@ impl PreparedProtocolOutputs { .append_to_output_sink(&mut prepared); } RendererOwnerAction::SharedWorkerTargetLifecycle(event) => { - if let Some((browser_context_id, _)) = - conn.target_owner_identity_for_route(session_id, owner.session_owner_route()) - { + if let Some((browser_context_id, _)) = conn.target_owner_identity_for_owner(owner) { crate::domains::target:: shared_worker_target_lifecycle_prepared_outputs_for_event( conn, @@ -375,9 +355,7 @@ impl PreparedProtocolOutputs { } } RendererOwnerAction::ServiceWorkerTargetLifecycle(event) => { - if let Some((browser_context_id, _)) = - conn.target_owner_identity_for_route(session_id, owner.session_owner_route()) - { + if let Some((browser_context_id, _)) = conn.target_owner_identity_for_owner(owner) { crate::domains::target:: service_worker_target_lifecycle_prepared_outputs_for_event( conn, diff --git a/moli-protocol/src/domains/activity/output_ingress/renderer.rs b/moli-protocol/src/domains/activity/output_ingress/renderer.rs index 7949a8e188..59cc37d5fd 100644 --- a/moli-protocol/src/domains/activity/output_ingress/renderer.rs +++ b/moli-protocol/src/domains/activity/output_ingress/renderer.rs @@ -28,10 +28,9 @@ fn renderer_owner_action_owner( if publication_owner.session_id().is_some() { return publication_owner.clone(); } - let Some((browser_context_id, target_id)) = conn.target_owner_identity_for_route( - publication_owner.session_id(), - publication_owner.session_owner_route(), - ) else { + let Some((browser_context_id, target_id)) = + conn.target_owner_identity_for_owner(publication_owner) + else { return publication_owner.clone(); }; let Some(target_id) = target_id else { @@ -132,7 +131,7 @@ async fn ingest_renderer_output_publication( projection, } => { let owner = CommandOwnerScope::for_session(&session_id); - project_renderer_output_records_for_route( + project_renderer_output_records_for_owner( conn, &owner, records, @@ -148,7 +147,7 @@ async fn ingest_renderer_output_publication( projection, } => { let owner = CommandOwnerScope::for_route(owner_route); - project_renderer_output_records_for_route( + project_renderer_output_records_for_owner( conn, &owner, records, @@ -162,7 +161,7 @@ async fn ingest_renderer_output_publication( } } -async fn project_renderer_output_records_for_route( +async fn project_renderer_output_records_for_owner( conn: &mut CdpConnection, owner: &CommandOwnerScope, records: Vec, @@ -301,10 +300,7 @@ mod tests { Some(&RendererRuntimeCommandCausalIdentity::new(None, 2)), ); assert_eq!( - conn.target_owner_identity_for_route( - implicit.session_id(), - implicit.session_owner_route(), - ), + conn.target_owner_identity_for_owner(&implicit,), Some(( "BID-owner-action".to_owned(), Some("TID-owner-action".to_owned()), diff --git a/moli-protocol/src/domains/activity/runtime_command_barrier.rs b/moli-protocol/src/domains/activity/runtime_command_barrier.rs index 921b16c717..3582f829ec 100644 --- a/moli-protocol/src/domains/activity/runtime_command_barrier.rs +++ b/moli-protocol/src/domains/activity/runtime_command_barrier.rs @@ -157,14 +157,10 @@ impl RuntimeCommandCausalOwner { } fn capture_for_scope(conn: &CdpConnection, scope: &CommandOwnerScope) -> Option { - if let Some(page) = conn.target_page_residence_identity_for_route( - scope.session_id(), - scope.session_owner_route(), - ) { + if let Some(page) = conn.target_page_residence_identity_for_owner(scope) { return Some(Self::Page(page)); } - let (browser_context_id, target_id) = - conn.target_owner_identity_for_route(scope.session_id(), scope.session_owner_route())?; + let (browser_context_id, target_id) = conn.target_owner_identity_for_owner(scope)?; Some(Self::Target { browser_context_id, target_id, diff --git a/moli-protocol/src/domains/activity/subresource.rs b/moli-protocol/src/domains/activity/subresource.rs index ba895e9a42..d912e77c91 100644 --- a/moli-protocol/src/domains/activity/subresource.rs +++ b/moli-protocol/src/domains/activity/subresource.rs @@ -43,9 +43,8 @@ impl PreparedSubresourceContinueAction { event: PendingSubresourceContinueEvent, ) -> Self { let internal_id = Self::internal_id(&event); - let request = conn.claim_subresource_continue_request_for_route( - command_owner.session_id(), - command_owner.session_owner_route(), + let request = conn.claim_subresource_continue_request_for_owner( + command_owner, &owner, internal_id, matches!(&event, PendingSubresourceContinueEvent::Completed { .. }), @@ -64,10 +63,7 @@ impl PreparedSubresourceContinueAction { event: PendingSubresourceContinueEvent, ) -> Option { let command_owner = CommandOwnerScope::capture(conn, session_id); - let owner = conn.target_page_residence_identity_for_route( - command_owner.session_id(), - command_owner.session_owner_route(), - )?; + let owner = conn.target_page_residence_identity_for_owner(&command_owner)?; Some(Self::capture(conn, &command_owner, owner, event)) } } @@ -78,17 +74,12 @@ pub(in crate::domains) fn prepare_subresource_continue_action_for_renderer_recor source_document: moli_core::RendererDocumentLifecycleIdentity, event: PendingSubresourceContinueEvent, ) -> Option { - if conn.target_root_document_lifecycle_identity_for_route( - command_owner.session_id(), - command_owner.session_owner_route(), - ) != Some(source_document) + if conn.target_root_document_lifecycle_identity_for_owner(command_owner) + != Some(source_document) { return None; } - let owner = conn.target_page_residence_identity_for_route( - command_owner.session_id(), - command_owner.session_owner_route(), - )?; + let owner = conn.target_page_residence_identity_for_owner(command_owner)?; Some(PreparedSubresourceContinueAction::capture( conn, command_owner, @@ -104,10 +95,7 @@ pub(in crate::domains) async fn flush_prepared_subresource_continue_actions_back actions: Vec, ) { for action in actions { - if conn.target_page_residence_identity_is_current_for_session( - command_owner.session_id(), - &action.owner, - ) { + if conn.target_page_residence_identity_is_current(&action.owner) { flush_prepared_subresource_continue_action_background_events_async( conn, out, @@ -126,9 +114,8 @@ async fn flush_prepared_subresource_continue_action_background_events_async( action: PreparedSubresourceContinueAction, ) { let session_id = command_owner.session_id(); - let owner_route = command_owner.session_owner_route(); let PreparedSubresourceContinueAction { event, request, .. } = action; - let fetch_session_id = conn.target_fetch_event_session_id_for_route(session_id, owner_route); + let fetch_session_id = conn.target_fetch_event_session_id_for_owner(command_owner); let fetch_event_session_id = fetch_session_id.as_deref().or(session_id); match event { @@ -160,9 +147,8 @@ async fn flush_prepared_subresource_continue_action_background_events_async( }; let Some(request_id) = in_flight.request_id else { let _ = conn - .continue_pending_subresource_response_for_route_async( - session_id, - owner_route, + .continue_pending_subresource_response_for_owner_async( + command_owner, response_info.internal_id, None, None, @@ -183,10 +169,7 @@ async fn flush_prepared_subresource_continue_action_background_events_async( .response_stage_url_match_policy .requires_final_url_match() && !conn - .target_fetch_subresource_interception_snapshot_for_route( - session_id, - owner_route, - ) + .target_fetch_subresource_interception_snapshot_for_owner(command_owner) .is_some_and(|snapshot| { snapshot.matches_response_stage( response_info.resource_type.into(), @@ -195,9 +178,8 @@ async fn flush_prepared_subresource_continue_action_background_events_async( }) { let _ = conn - .continue_pending_subresource_response_for_route_async( - session_id, - owner_route, + .continue_pending_subresource_response_for_owner_async( + command_owner, response_info.internal_id, None, None, @@ -215,18 +197,15 @@ async fn flush_prepared_subresource_continue_action_background_events_async( return; } let blocked_intercepts = if in_flight.response_stage_blocked_intercepts.is_empty() { - conn.target_fetch_subresource_interception_snapshot_for_route( - session_id, - owner_route, - ) - .map(|snapshot| { - snapshot.matching_network_intercepts( - FetchRequestStage::Response, - response_info.resource_type.into(), - &response_info.final_url, - ) - }) - .unwrap_or_default() + conn.target_fetch_subresource_interception_snapshot_for_owner(command_owner) + .map(|snapshot| { + snapshot.matching_network_intercepts( + FetchRequestStage::Response, + response_info.resource_type.into(), + &response_info.final_url, + ) + }) + .unwrap_or_default() } else { in_flight.response_stage_blocked_intercepts.clone() }; @@ -248,10 +227,7 @@ async fn flush_prepared_subresource_continue_action_background_events_async( &in_flight.pending.frame_id, ) .or_else(|| { - conn.target_fetch_subresource_interception_snapshot_for_route( - session_id, - owner_route, - ) + conn.target_fetch_subresource_interception_snapshot_for_owner(command_owner) }) .map(|snapshot| { snapshot.matching_response_stage_pause_sessions( @@ -277,10 +253,7 @@ async fn flush_prepared_subresource_continue_action_background_events_async( let mut remaining_sessions = Vec::new(); for session in response_stage_sessions.into_iter().skip(1) { let Ok((next_request_id, _)) = conn - .allocate_pending_subresource_fetch_request_ids_for_route( - session_id, - owner_route, - ) + .allocate_pending_subresource_fetch_request_ids_for_owner(command_owner) else { return; }; @@ -305,13 +278,11 @@ async fn flush_prepared_subresource_continue_action_background_events_async( pending_response.action_session_id = response_event_session_id.clone(); let pending_owner_session_id = pending_response.owner_session_id.clone(); let pending_owner_session_id = pending_owner_session_id.as_deref().or(session_id); - let pending_owner_route = pending_owner_session_id - .is_none() - .then_some(owner_route) - .flatten(); - if !conn.register_pending_subresource_fetch_response_request_for_route( - pending_owner_session_id, - pending_owner_route, + let pending_owner = pending_owner_session_id + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| command_owner.clone()); + if !conn.register_pending_subresource_fetch_response_request_for_owner( + &pending_owner, request_id.clone(), pending_response.clone(), ) { @@ -332,9 +303,8 @@ async fn flush_prepared_subresource_continue_action_background_events_async( }; let Some(request_id) = in_flight.request_id else { let _ = conn - .fail_pending_subresource_auth_for_route_async( - session_id, - owner_route, + .fail_pending_subresource_auth_for_owner_async( + command_owner, auth_info.internal_id, "Fetch auth challenge has no DevTools request".to_owned(), ) @@ -351,7 +321,7 @@ async fn flush_prepared_subresource_continue_action_background_events_async( return; }; let blocked_intercepts = conn - .target_fetch_subresource_interception_snapshot_for_route(session_id, owner_route) + .target_fetch_subresource_interception_snapshot_for_owner(command_owner) .map(|snapshot| snapshot.matching_auth_required_network_intercepts(&auth_info.url)) .unwrap_or_default(); let blocked_intercepts = if blocked_intercepts.is_empty() { @@ -376,10 +346,7 @@ async fn flush_prepared_subresource_continue_action_background_events_async( &in_flight.pending.frame_id, ) .or_else(|| { - conn.target_fetch_subresource_interception_snapshot_for_route( - session_id, - owner_route, - ) + conn.target_fetch_subresource_interception_snapshot_for_owner(command_owner) }) .map(|snapshot| { snapshot.matching_auth_required_pause_sessions(session_id, &auth_info.url) @@ -401,10 +368,7 @@ async fn flush_prepared_subresource_continue_action_background_events_async( let mut remaining_sessions = Vec::new(); for session in auth_sessions.into_iter().skip(1) { let Ok((next_request_id, _)) = conn - .allocate_pending_subresource_fetch_request_ids_for_route( - session_id, - owner_route, - ) + .allocate_pending_subresource_fetch_request_ids_for_owner(command_owner) else { return; }; @@ -429,13 +393,11 @@ async fn flush_prepared_subresource_continue_action_background_events_async( pending_auth.action_session_id = auth_event_session_id.clone(); let pending_owner_session_id = pending_auth.owner_session_id.clone(); let pending_owner_session_id = pending_owner_session_id.as_deref().or(session_id); - let pending_owner_route = pending_owner_session_id - .is_none() - .then_some(owner_route) - .flatten(); - if !conn.register_pending_subresource_fetch_auth_request_for_route( - pending_owner_session_id, - pending_owner_route, + let pending_owner = pending_owner_session_id + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| command_owner.clone()); + if !conn.register_pending_subresource_fetch_auth_request_for_owner( + &pending_owner, request_id.clone(), pending_auth.clone(), ) { @@ -658,10 +620,7 @@ async fn flush_post_subresource_network_activity_background_events_async( frame_id: &str, network_request_id: &str, ) { - conn.ingest_runtime_session_owner_output_updates_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + conn.ingest_runtime_session_owner_output_updates_for_owner(owner); project_network_backlog_for_owner(conn, out, owner, frame_id, Some(network_request_id)); clear_fetch_pause_network_announcement(conn, owner, network_request_id); } @@ -692,9 +651,7 @@ fn clear_fetch_pause_network_announcement( owner: &CommandOwnerScope, request_id: &str, ) { - if let Ok(runtime_slot) = conn - .runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) - { + if let Ok(runtime_slot) = conn.runtime_session_owner_slot_mut_for_owner(owner) { runtime_slot.clear_fetch_pause_announced_request_id(request_id); } } @@ -708,9 +665,7 @@ fn record_subresource_network_request_handle( let Some(request_handle) = request_handle else { return; }; - if let Ok(runtime_slot) = conn - .runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) - { + if let Ok(runtime_slot) = conn.runtime_session_owner_slot_mut_for_owner(owner) { runtime_slot.record_subresource_request_id_for_handle_if_absent( request_handle, request_id.to_owned(), diff --git a/moli-protocol/src/domains/autofill.rs b/moli-protocol/src/domains/autofill.rs index 24f8655c05..c21fc306c8 100644 --- a/moli-protocol/src/domains/autofill.rs +++ b/moli-protocol/src/domains/autofill.rs @@ -130,10 +130,8 @@ pub(crate) fn complete_pending_autofill_command( conn: &mut CdpConnection, completed: CompletedAutofillCommandDispatch, ) -> CommandOutputPlan { - let session_id = completed.owner_scope.session_id(); - let owner_route = completed.owner_scope.session_owner_route(); let outcome = completed.completed.and_then(|completion| { - conn.loaded_page_mut_for_protocol_access_for_route(session_id, owner_route) + conn.loaded_page_mut_for_protocol_access_for_owner(&completed.owner_scope) .and_then(|page| { page.finish_autofill_trigger(completion) .map_err(|error| error.to_string()) diff --git a/moli-protocol/src/domains/css.rs b/moli-protocol/src/domains/css.rs index cfb467aad9..7dbabf0d17 100644 --- a/moli-protocol/src/domains/css.rs +++ b/moli-protocol/src/domains/css.rs @@ -399,10 +399,7 @@ pub(crate) fn complete_pending_css_command( } = completed; let session_id = owner_scope.session_id(); let Some(page) = conn - .loaded_page_mut_for_protocol_access_for_route( - session_id, - owner_scope.session_owner_route(), - ) + .loaded_page_mut_for_protocol_access_for_owner(&owner_scope) .ok() else { return CssCommandDispatchStep::Complete(CommandOutputPlan::error( diff --git a/moli-protocol/src/domains/debugger.rs b/moli-protocol/src/domains/debugger.rs index 806679dc96..341c15b608 100644 --- a/moli-protocol/src/domains/debugger.rs +++ b/moli-protocol/src/domains/debugger.rs @@ -152,11 +152,14 @@ mod tests { .map(str::to_owned) .expect("Debugger.scriptParsed for the suspended-renderer source"); + let navigation_owner = CommandOwnerScope::capture(&ctx.conn, None); let navigation = ctx .conn - .start_document_navigation_for_route(None, None, "LOADER-debugger-interrupt".to_owned()) + .start_document_navigation_for_owner( + &navigation_owner, + "LOADER-debugger-interrupt".to_owned(), + ) .expect("start cross-Document navigation"); - let navigation_owner = CommandOwnerScope::capture(&ctx.conn, None); assert!( ctx.conn .renderer_document_navigation_is_suspended_for_session_owner(None) diff --git a/moli-protocol/src/domains/dom.rs b/moli-protocol/src/domains/dom.rs index 1a78b8acf2..f2e367c395 100644 --- a/moli-protocol/src/domains/dom.rs +++ b/moli-protocol/src/domains/dom.rs @@ -145,15 +145,12 @@ pub(crate) fn dom_agent_enabled_for_session( conn: &CdpConnection, session_id: Option<&str>, ) -> bool { - dom_agent_enabled_for_route(conn, session_id, None) + let owner = CommandOwnerScope::capture(conn, session_id); + dom_agent_enabled_for_owner(conn, &owner) } -pub(crate) fn dom_agent_enabled_for_route( - conn: &CdpConnection, - session_id: Option<&str>, - owner_route: Option<&crate::conn::CdpSessionRoute>, -) -> bool { - conn.target_devtools_session_state_for_route(session_id, owner_route) +pub(crate) fn dom_agent_enabled_for_owner(conn: &CdpConnection, owner: &CommandOwnerScope) -> bool { + conn.target_devtools_session_state_for_owner(owner) .is_some_and(|state| state.dom_session_state.enabled) } @@ -179,12 +176,11 @@ fn disable_dom_agent_for_session(conn: &mut CdpConnection, session_id: Option<&s .is_some() } -pub(crate) fn dom_agent_includes_whitespace_for_route( +pub(crate) fn dom_agent_includes_whitespace_for_owner( conn: &CdpConnection, - session_id: Option<&str>, - owner_route: Option<&crate::conn::CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> bool { - conn.target_devtools_session_state_for_route(session_id, owner_route) + conn.target_devtools_session_state_for_owner(owner) .is_some_and(|state| { state.dom_session_state.enabled && state.dom_session_state.include_whitespace }) @@ -194,25 +190,19 @@ fn loaded_page_mut_for_owner<'a>( conn: &'a mut CdpConnection, owner: &CommandOwnerScope, ) -> Option<&'a mut Page> { - conn.loaded_page_mut_for_protocol_access_for_route( - owner.session_id(), - owner.session_owner_route(), - ) - .ok() + conn.loaded_page_mut_for_protocol_access_for_owner(owner) + .ok() } fn target_owner_exists_for_owner(conn: &CdpConnection, owner: &CommandOwnerScope) -> bool { - conn.target_owner_identity_for_route(owner.session_id(), owner.session_owner_route()) + conn.target_owner_identity_for_owner(owner) .and_then(|(_, target_id)| target_id) .is_some() } fn top_frame_id_for_owner(conn: &CdpConnection, owner: &CommandOwnerScope) -> Option { - conn.target_session_owner_frame_tree_identity_for_route( - owner.session_id(), - owner.session_owner_route(), - ) - .map(|(frame_id, _, _, _)| frame_id) + conn.target_session_owner_frame_tree_identity_for_owner(owner) + .map(|(frame_id, _, _, _)| frame_id) } fn cached_dom_remote_object_node_for_owner( @@ -220,8 +210,7 @@ fn cached_dom_remote_object_node_for_owner( owner: &CommandOwnerScope, object_id: &str, ) -> Option { - let (browser_context_id, target_id) = - conn.target_owner_identity_for_route(owner.session_id(), owner.session_owner_route())?; + let (browser_context_id, target_id) = conn.target_owner_identity_for_owner(owner)?; let browser_context = conn.browser_context_by_id(&browser_context_id)?; let target_id = target_id .as_deref() @@ -239,9 +228,7 @@ fn cache_dom_remote_object_node_for_owner( object_id: String, node: Value, ) { - let Some((browser_context_id, target_id)) = - conn.target_owner_identity_for_route(owner.session_id(), owner.session_owner_route()) - else { + let Some((browser_context_id, target_id)) = conn.target_owner_identity_for_owner(owner) else { return; }; if let Some(browser_context) = conn.browser_context_by_id_mut(&browser_context_id) { diff --git a/moli-protocol/src/domains/dom/activity.rs b/moli-protocol/src/domains/dom/activity.rs index 7bd07fa66b..90a626f55d 100644 --- a/moli-protocol/src/domains/dom/activity.rs +++ b/moli-protocol/src/domains/dom/activity.rs @@ -87,10 +87,7 @@ impl DomPreparedOutputs { batches: &[RendererDomMutationEventBatch], ) -> Self { let current_attachment = conn - .runtime_session_owner_slot_for_route( - source_owner.session_id(), - source_owner.session_owner_route(), - ) + .runtime_session_owner_slot_for_owner(source_owner) .ok() .and_then(|slot| slot.current_renderer_attachment()); Self { diff --git a/moli-protocol/src/domains/dom/child_frame.rs b/moli-protocol/src/domains/dom/child_frame.rs index 7cb0c0c695..831ae56e92 100644 --- a/moli-protocol/src/domains/dom/child_frame.rs +++ b/moli-protocol/src/domains/dom/child_frame.rs @@ -1,7 +1,7 @@ use serde_json::json; use super::{ - dom_agent_includes_whitespace_for_route, frontend_binding, node_snapshot_to_cdp, + dom_agent_includes_whitespace_for_owner, frontend_binding, node_snapshot_to_cdp, resolve::{ PendingDomCommandStartError, attributes_result_from_renderer_resolution, devtools_dom_geometry_result_from_renderer, property_result_from_renderer_resolution, @@ -9,12 +9,12 @@ use super::{ text_result_from_renderer_resolution, }, }; -use crate::conn::{CdpConnection, CdpSessionRoute}; +use crate::conn::{CdpConnection, CommandOwnerScope}; use crate::devtools_runtime::{ DevToolsCommand, DevToolsCommandResult, DevToolsDescribeNodeCommand, DevToolsDescribeNodeResult, DevToolsDomGeometryCommand, DevToolsDomGeometryResult, DevToolsDomNodeReference, DevToolsGetAttributesResult, DevToolsGetOuterHtmlCommand, - DevToolsGetOuterHtmlResult, DevToolsGetPropertyResult, DevToolsGetTextResult, DevToolsProtocol, + DevToolsGetOuterHtmlResult, DevToolsGetPropertyResult, DevToolsGetTextResult, DevToolsQuerySelectorResult, DevToolsResolveNodeCommand, DevToolsResolveNodeResult, DevToolsScrollIntoViewIfNeededCommand, }; @@ -23,24 +23,32 @@ use moli_core::page::{ RendererDocumentNodeReference, }; -fn loaded_page_mut_for_route<'a>( +fn loaded_page_mut_for_owner<'a>( conn: &'a mut CdpConnection, - session_id: Option<&str>, - owner_route: &CdpSessionRoute, + owner: &CommandOwnerScope, ) -> Option<&'a mut Page> { - conn.loaded_page_mut_for_protocol_access_for_route(session_id, Some(owner_route)) + conn.loaded_page_mut_for_protocol_access_for_owner(owner) .ok() } +fn renderer_inspector_session_id_for_owner( + conn: &CdpConnection, + owner: &CommandOwnerScope, +) -> Option { + conn.target_renderer_runtime_inspector_session_id_for_owner(owner) +} + pub(super) async fn execute_devtools_dom_command( conn: &mut CdpConnection, frame_id: &str, + owner: &CommandOwnerScope, command: DevToolsCommand, ) -> Result { match command { DevToolsCommand::QuerySelector(command) => { let result = query_selector_command( conn, + owner, frame_id, command.root, &command.selector, @@ -50,47 +58,43 @@ pub(super) async fn execute_devtools_dom_command( Ok(DevToolsCommandResult::QuerySelector(result)) } DevToolsCommand::GetAttributes(command) => { - let result = attributes_command(conn, frame_id, command.reference).await?; + let result = attributes_command(conn, owner, command.reference).await?; Ok(DevToolsCommandResult::GetAttributes(result)) } DevToolsCommand::GetText(command) => { - let result = text_command(conn, frame_id, command.reference).await?; + let result = text_command(conn, owner, command.reference).await?; Ok(DevToolsCommandResult::GetText(result)) } DevToolsCommand::GetProperty(command) => { - let result = property_command(conn, frame_id, command.reference, &command.name).await?; + let result = property_command(conn, owner, command.reference, &command.name).await?; Ok(DevToolsCommandResult::GetProperty(result)) } DevToolsCommand::GetOuterHtml(command) => { let DevToolsGetOuterHtmlCommand { - context, + context: _, reference, include_shadow_dom, } = command; - let session_id = (context.protocol == DevToolsProtocol::Cdp) - .then(|| context.session_id.as_ref().map(|id| id.as_str())) - .flatten(); let outer_html = - outer_html_command(conn, session_id, frame_id, reference, include_shadow_dom) - .await?; + outer_html_command(conn, owner, frame_id, reference, include_shadow_dom).await?; Ok(DevToolsCommandResult::GetOuterHtml( DevToolsGetOuterHtmlResult { outer_html }, )) } DevToolsCommand::DescribeNode(command) => { - let result = describe_node_command(conn, frame_id, command).await?; + let result = describe_node_command(conn, owner, frame_id, command).await?; Ok(DevToolsCommandResult::DescribeNode(result)) } DevToolsCommand::ResolveNode(command) => { - let result = resolve_node_command(conn, frame_id, command).await?; + let result = resolve_node_command(conn, owner, command).await?; Ok(DevToolsCommandResult::ResolveNode(result)) } DevToolsCommand::DomGeometry(command) => { - let result = dom_geometry_command(conn, frame_id, command).await?; + let result = dom_geometry_command(conn, owner, command).await?; Ok(DevToolsCommandResult::DomGeometry(result)) } DevToolsCommand::ScrollIntoViewIfNeeded(command) => { - scroll_into_view_if_needed_command(conn, frame_id, command).await?; + scroll_into_view_if_needed_command(conn, owner, command).await?; Ok(DevToolsCommandResult::Empty) } _ => Err(PendingDomCommandStartError::no_such_target()), @@ -99,43 +103,27 @@ pub(super) async fn execute_devtools_dom_command( async fn query_selector_command( conn: &mut CdpConnection, - frame_id: &str, - root: Option, - selector: &str, - multiple: bool, -) -> Result { - let route = conn - .target_session_route_for_child_frame_id(frame_id) - .ok_or_else(PendingDomCommandStartError::no_such_target)?; - query_selector_command_in_session(conn, None, &route, frame_id, root, selector, multiple).await -} - -async fn query_selector_command_in_session( - conn: &mut CdpConnection, - session_id: Option<&str>, - owner_route: &CdpSessionRoute, + owner: &CommandOwnerScope, frame_id: &str, root: Option, selector: &str, multiple: bool, ) -> Result { let renderer_inspector_session_id = - conn.target_renderer_runtime_inspector_session_id_for_route(session_id, Some(owner_route)); - let include_whitespace = - dom_agent_includes_whitespace_for_route(conn, session_id, Some(owner_route)); + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); + let include_whitespace = dom_agent_includes_whitespace_for_owner(conn, owner); let root_backend_node_id = match root { Some(reference) => { - let reference = - resolve_frontend_node_reference(conn, session_id, owner_route, reference).await?; + let reference = resolve_frontend_node_reference(conn, owner, reference).await?; required_child_frame_backend_node_id(&reference)? } None => { - child_frame_document_root_node_reference(conn, session_id, owner_route, frame_id) + child_frame_document_root_node_reference(conn, owner, frame_id) .await? .backend_node_id } }; - let page = loaded_page_mut_for_route(conn, session_id, owner_route) + let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let pending = page .start_child_frame_document_query_selector_for_backend_node_id( @@ -159,16 +147,14 @@ async fn query_selector_command_in_session( async fn resolve_frontend_node_reference( conn: &mut CdpConnection, - session_id: Option<&str>, - owner_route: &CdpSessionRoute, + owner: &CommandOwnerScope, reference: DevToolsDomNodeReference, ) -> Result { let DevToolsDomNodeReference::FrontendNodeId(frontend_node_id) = reference else { return Ok(reference); }; - let renderer_inspector_session_id = - conn.target_renderer_runtime_inspector_session_id_for_route(session_id, Some(owner_route)); - let page = loaded_page_mut_for_route(conn, session_id, owner_route) + let renderer_inspector_session_id = renderer_inspector_session_id_for_owner(conn, owner); + let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let pending = page .start_document_frontend_node_binding(renderer_inspector_session_id, frontend_node_id) @@ -177,7 +163,7 @@ async fn resolve_frontend_node_reference( .wait() .await .map_err(PendingDomCommandStartError::renderer_error)?; - let page = loaded_page_mut_for_route(conn, session_id, owner_route) + let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; frontend_binding::finish_reference(page, completion).map_err(|message| { PendingDomCommandStartError { @@ -189,13 +175,11 @@ async fn resolve_frontend_node_reference( async fn child_frame_document_root_node_reference( conn: &mut CdpConnection, - session_id: Option<&str>, - owner_route: &CdpSessionRoute, + owner: &CommandOwnerScope, frame_id: &str, ) -> Result { - let renderer_inspector_session_id = - conn.target_renderer_runtime_inspector_session_id_for_route(session_id, Some(owner_route)); - let page = loaded_page_mut_for_route(conn, session_id, owner_route) + let renderer_inspector_session_id = renderer_inspector_session_id_for_owner(conn, owner); + let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let pending = page .start_child_frame_document_root_node_reference(frame_id, renderer_inspector_session_id) @@ -204,7 +188,7 @@ async fn child_frame_document_root_node_reference( .wait() .await .map_err(PendingDomCommandStartError::renderer_error)?; - let page = loaded_page_mut_for_route(conn, session_id, owner_route) + let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; page.finish_document_node_reference(completion) .map_err(PendingDomCommandStartError::renderer_error)? @@ -213,14 +197,11 @@ async fn child_frame_document_root_node_reference( async fn attributes_command( conn: &mut CdpConnection, - frame_id: &str, + owner: &CommandOwnerScope, reference: DevToolsDomNodeReference, ) -> Result { - let route = conn - .target_session_route_for_child_frame_id(frame_id) - .ok_or_else(PendingDomCommandStartError::no_such_target)?; - let reference = resolve_frontend_node_reference(conn, None, &route, reference).await?; - let page = loaded_page_mut_for_route(conn, None, &route) + let reference = resolve_frontend_node_reference(conn, owner, reference).await?; + let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let pending = start_document_node_attributes_for_reference(page, reference)?; let completion = pending @@ -243,14 +224,11 @@ fn start_document_node_attributes_for_reference( async fn text_command( conn: &mut CdpConnection, - frame_id: &str, + owner: &CommandOwnerScope, reference: DevToolsDomNodeReference, ) -> Result { - let route = conn - .target_session_route_for_child_frame_id(frame_id) - .ok_or_else(PendingDomCommandStartError::no_such_target)?; - let reference = resolve_frontend_node_reference(conn, None, &route, reference).await?; - let page = loaded_page_mut_for_route(conn, None, &route) + let reference = resolve_frontend_node_reference(conn, owner, reference).await?; + let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let pending = start_document_node_text_for_reference(page, reference)?; let completion = pending @@ -273,15 +251,12 @@ fn start_document_node_text_for_reference( async fn property_command( conn: &mut CdpConnection, - frame_id: &str, + owner: &CommandOwnerScope, reference: DevToolsDomNodeReference, name: &str, ) -> Result { - let route = conn - .target_session_route_for_child_frame_id(frame_id) - .ok_or_else(PendingDomCommandStartError::no_such_target)?; - let reference = resolve_frontend_node_reference(conn, None, &route, reference).await?; - let page = loaded_page_mut_for_route(conn, None, &route) + let reference = resolve_frontend_node_reference(conn, owner, reference).await?; + let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let pending = start_document_node_property_for_reference(page, reference, name)?; let completion = pending @@ -305,48 +280,24 @@ fn start_document_node_property_for_reference( async fn outer_html_command( conn: &mut CdpConnection, - session_id: Option<&str>, - frame_id: &str, - reference: Option, - include_shadow_dom: bool, -) -> Result { - let route = conn - .target_session_route_for_child_frame_id(frame_id) - .ok_or_else(PendingDomCommandStartError::no_such_target)?; - outer_html_command_in_session( - conn, - session_id, - &route, - frame_id, - reference, - include_shadow_dom, - ) - .await -} - -async fn outer_html_command_in_session( - conn: &mut CdpConnection, - session_id: Option<&str>, - owner_route: &CdpSessionRoute, + owner: &CommandOwnerScope, frame_id: &str, reference: Option, include_shadow_dom: bool, ) -> Result { let reference = match reference { - Some(reference) => { - Some(resolve_frontend_node_reference(conn, session_id, owner_route, reference).await?) - } + Some(reference) => Some(resolve_frontend_node_reference(conn, owner, reference).await?), None => None, }; let backend_node_id = match reference { Some(reference) => required_child_frame_backend_node_id(&reference)?, None => { - child_frame_document_root_node_reference(conn, session_id, owner_route, frame_id) + child_frame_document_root_node_reference(conn, owner, frame_id) .await? .backend_node_id } }; - let page = loaded_page_mut_for_route(conn, session_id, owner_route) + let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let pending = page .start_outer_html_for_backend_node_id(backend_node_id, include_shadow_dom) @@ -362,28 +313,14 @@ async fn outer_html_command_in_session( async fn resolve_node_command( conn: &mut CdpConnection, - frame_id: &str, + owner: &CommandOwnerScope, command: DevToolsResolveNodeCommand, ) -> Result { - let route = conn - .target_session_route_for_child_frame_id(frame_id) - .ok_or_else(PendingDomCommandStartError::no_such_target)?; - resolve_node_command_in_session(conn, None, &route, command).await -} - -async fn resolve_node_command_in_session( - conn: &mut CdpConnection, - session_id: Option<&str>, - owner_route: &CdpSessionRoute, - command: DevToolsResolveNodeCommand, -) -> Result { - let reference = - resolve_frontend_node_reference(conn, session_id, owner_route, command.reference).await?; + let reference = resolve_frontend_node_reference(conn, owner, command.reference).await?; let object_group = command.object_group; - let renderer_inspector_session_id = - conn.target_renderer_runtime_inspector_session_id_for_route(session_id, Some(owner_route)); + let renderer_inspector_session_id = renderer_inspector_session_id_for_owner(conn, owner); let remote_object = { - let page = loaded_page_mut_for_route(conn, session_id, owner_route) + let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let backend_node_id = required_child_frame_backend_node_id(&reference)?; let pending = page @@ -422,18 +359,13 @@ async fn resolve_node_command_in_session( } let result = json!({ "object": remote_object.clone() }); if let Some(object_group) = object_group.as_deref() { - conn.register_runtime_remote_object_ids_from_value_for_route_with_group( - session_id, - Some(owner_route), + conn.register_runtime_remote_object_ids_from_value_for_owner_with_group( + owner, &result, object_group, ); } else { - conn.register_runtime_remote_object_ids_from_value_for_route( - session_id, - Some(owner_route), - &result, - ); + conn.register_runtime_remote_object_ids_from_value_for_owner(owner, &result); } Ok(DevToolsResolveNodeResult { object: remote_object, @@ -442,24 +374,21 @@ async fn resolve_node_command_in_session( async fn describe_node_command( conn: &mut CdpConnection, + owner: &CommandOwnerScope, frame_id: &str, command: DevToolsDescribeNodeCommand, ) -> Result { let DevToolsDescribeNodeCommand { - context, + context: _, reference, depth, pierce, } = command; - let session_id = (context.protocol == DevToolsProtocol::Cdp) - .then(|| context.session_id.as_ref().map(|id| id.as_str())) - .flatten(); let snapshot = match reference { Some(reference) => { - node_snapshot_for_reference(conn, session_id, frame_id, reference, depth, pierce) - .await? + node_snapshot_for_reference(conn, owner, reference, depth, pierce).await? } - None => child_frame_root_node_snapshot(conn, session_id, frame_id, depth, pierce).await?, + None => child_frame_root_node_snapshot(conn, owner, frame_id, depth, pierce).await?, }; let Some(node) = node_snapshot_to_cdp(&snapshot, Some(snapshot.node_id), Some(frame_id)) else { return Err(PendingDomCommandStartError::node_not_found()); @@ -469,33 +398,15 @@ async fn describe_node_command( async fn node_snapshot_for_reference( conn: &mut CdpConnection, - session_id: Option<&str>, - frame_id: &str, + owner: &CommandOwnerScope, reference: DevToolsDomNodeReference, depth: i32, pierce: bool, ) -> Result { - let route = conn - .target_session_route_for_child_frame_id(frame_id) - .ok_or_else(PendingDomCommandStartError::no_such_target)?; - node_snapshot_for_reference_in_session(conn, session_id, &route, reference, depth, pierce).await -} - -async fn node_snapshot_for_reference_in_session( - conn: &mut CdpConnection, - session_id: Option<&str>, - owner_route: &CdpSessionRoute, - reference: DevToolsDomNodeReference, - depth: i32, - pierce: bool, -) -> Result { - let reference = - resolve_frontend_node_reference(conn, session_id, owner_route, reference).await?; - let renderer_inspector_session_id = - conn.target_renderer_runtime_inspector_session_id_for_route(session_id, Some(owner_route)); - let include_whitespace = - dom_agent_includes_whitespace_for_route(conn, session_id, Some(owner_route)); - let page = loaded_page_mut_for_route(conn, session_id, owner_route) + let reference = resolve_frontend_node_reference(conn, owner, reference).await?; + let renderer_inspector_session_id = renderer_inspector_session_id_for_owner(conn, owner); + let include_whitespace = dom_agent_includes_whitespace_for_owner(conn, owner); + let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let backend_node_id = required_child_frame_backend_node_id(&reference)?; let pending = page @@ -519,23 +430,17 @@ async fn node_snapshot_for_reference_in_session( async fn child_frame_root_node_snapshot( conn: &mut CdpConnection, - session_id: Option<&str>, + owner: &CommandOwnerScope, frame_id: &str, depth: i32, pierce: bool, ) -> Result { - let route = conn - .target_session_route_for_child_frame_id(frame_id) - .ok_or_else(PendingDomCommandStartError::no_such_target)?; - let backend_node_id = - child_frame_document_root_node_reference(conn, session_id, &route, frame_id) - .await? - .backend_node_id; - let renderer_inspector_session_id = - conn.target_renderer_runtime_inspector_session_id_for_route(session_id, Some(&route)); - let include_whitespace = - dom_agent_includes_whitespace_for_route(conn, session_id, Some(&route)); - let page = loaded_page_mut_for_route(conn, session_id, &route) + let backend_node_id = child_frame_document_root_node_reference(conn, owner, frame_id) + .await? + .backend_node_id; + let renderer_inspector_session_id = renderer_inspector_session_id_for_owner(conn, owner); + let include_whitespace = dom_agent_includes_whitespace_for_owner(conn, owner); + let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let pending = page .start_document_node_snapshot_for_backend_node_id_in_inspector_session( @@ -558,10 +463,10 @@ async fn child_frame_root_node_snapshot( async fn dom_geometry_command( conn: &mut CdpConnection, - frame_id: &str, + owner: &CommandOwnerScope, command: DevToolsDomGeometryCommand, ) -> Result { - let geometry = document_geometry_for_reference(conn, frame_id, command.reference).await?; + let geometry = document_geometry_for_reference(conn, owner, command.reference).await?; devtools_dom_geometry_result_from_renderer(command.operation, geometry).map_err(|error| { PendingDomCommandStartError { code: -32000, @@ -572,7 +477,7 @@ async fn dom_geometry_command( async fn scroll_into_view_if_needed_command( conn: &mut CdpConnection, - frame_id: &str, + owner: &CommandOwnerScope, command: DevToolsScrollIntoViewIfNeededCommand, ) -> Result<(), PendingDomCommandStartError> { let Some(reference) = command.reference else { @@ -581,7 +486,7 @@ async fn scroll_into_view_if_needed_command( // The lightweight headless renderer currently treats scrollIntoViewIfNeeded // as a geometry-validating no-op. Match the top-level path for child-frame // elements: prove the referenced node has geometry, then complete. - match document_geometry_for_reference(conn, frame_id, reference).await? { + match document_geometry_for_reference(conn, owner, reference).await? { RendererDocumentNodeGeometry::FoundElement { .. } => Ok(()), RendererDocumentNodeGeometry::FoundNonElement { .. } | RendererDocumentNodeGeometry::NoLayoutObject @@ -594,24 +499,11 @@ async fn scroll_into_view_if_needed_command( async fn document_geometry_for_reference( conn: &mut CdpConnection, - frame_id: &str, + owner: &CommandOwnerScope, reference: DevToolsDomNodeReference, ) -> Result { - let route = conn - .target_session_route_for_child_frame_id(frame_id) - .ok_or_else(PendingDomCommandStartError::no_such_target)?; - document_geometry_for_reference_in_session(conn, None, &route, reference).await -} - -async fn document_geometry_for_reference_in_session( - conn: &mut CdpConnection, - session_id: Option<&str>, - owner_route: &CdpSessionRoute, - reference: DevToolsDomNodeReference, -) -> Result { - let reference = - resolve_frontend_node_reference(conn, session_id, owner_route, reference).await?; - let page = loaded_page_mut_for_route(conn, session_id, owner_route) + let reference = resolve_frontend_node_reference(conn, owner, reference).await?; + let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let backend_node_id = required_child_frame_backend_node_id(&reference)?; let pending = page diff --git a/moli-protocol/src/domains/dom/resolve.rs b/moli-protocol/src/domains/dom/resolve.rs index 94ef60e505..1757a375d2 100644 --- a/moli-protocol/src/domains/dom/resolve.rs +++ b/moli-protocol/src/domains/dom/resolve.rs @@ -318,11 +318,8 @@ pub(super) fn start_disable_dom_agent_command( cmd: &Cmd<'_>, ) -> Result, PendingDomCommandStartError> { let owner = CommandOwnerScope::capture(conn, cmd.session_id); - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(&owner); let Some(page) = loaded_page_mut_for_owner(conn, &owner) else { return Ok(None); }; @@ -817,8 +814,7 @@ fn start_pending_dom_command( }); } if action.requires_document_access() - && let Err(message) = conn - .ensure_document_accessible_for_route(owner.session_id(), owner.session_owner_route()) + && let Err(message) = conn.ensure_document_accessible_for_owner(&owner) { return Err(PendingDomCommandStartError { code: -32000, @@ -1262,11 +1258,8 @@ fn start_cdp_dom_edit_command( ) -> Result { let owner = CommandOwnerScope::capture(conn, cmd.session_id); let edit = super::edit::renderer_dom_edit_from_cdp(cmd, action)?; - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(&owner); let page = loaded_page_mut_for_owner(conn, &owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let pending = page @@ -1465,16 +1458,9 @@ fn start_devtools_describe_node_command( }, ); } - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); - let include_whitespace = dom_agent_includes_whitespace_for_route( - conn, - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); + let include_whitespace = dom_agent_includes_whitespace_for_owner(conn, owner); let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let pending = start_inspector_document_node_snapshot_for_reference( @@ -1536,16 +1522,9 @@ fn start_devtools_request_child_nodes_command( command: DevToolsRequestChildNodesCommand, ) -> Result, PendingDomCommandStartError> { let top_frame_id = top_frame_id_for_owner(conn, owner); - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); - let include_whitespace = dom_agent_includes_whitespace_for_route( - conn, - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); + let include_whitespace = dom_agent_includes_whitespace_for_owner(conn, owner); let next_depth = if command.depth > 0 { command.depth - 1 } else { @@ -1675,16 +1654,9 @@ fn start_devtools_query_selector_command( command: DevToolsQuerySelectorCommand, ) -> Result, PendingDomCommandStartError> { let top_frame_id = top_frame_id_for_owner(conn, owner); - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); - let include_whitespace = dom_agent_includes_whitespace_for_route( - conn, - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); + let include_whitespace = dom_agent_includes_whitespace_for_owner(conn, owner); let Some(reference) = command.root else { let page = loaded_page_mut_for_owner(conn, owner).ok_or_else(|| PendingDomCommandStartError { @@ -1910,16 +1882,9 @@ fn start_devtools_get_document_command( PendingDomDocumentSnapshotOperation::GetDocument }; let top_frame_id = top_frame_id_for_owner(conn, owner); - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); - let include_whitespace = dom_agent_includes_whitespace_for_route( - conn, - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); + let include_whitespace = dom_agent_includes_whitespace_for_owner(conn, owner); let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let depth = match operation { @@ -1969,11 +1934,8 @@ fn start_devtools_get_frame_owner_command( owner: &CommandOwnerScope, command: DevToolsGetFrameOwnerCommand, ) -> Result, PendingDomCommandStartError> { - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); let page = loaded_page_mut_for_owner(conn, owner).ok_or_else(|| PendingDomCommandStartError { code: -32000, @@ -2029,16 +1991,10 @@ fn start_devtools_get_node_for_location_command( command: DevToolsGetNodeForLocationCommand, ) -> Result, PendingDomCommandStartError> { let top_frame_id = conn - .target_session_owner_frame_tree_identity_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + .target_session_owner_frame_tree_identity_for_owner(owner) .map(|identity| identity.0) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; - let inspector_session_id = conn.target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let inspector_session_id = conn.target_renderer_runtime_inspector_session_id_for_owner(owner); let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let pending = page @@ -2130,11 +2086,8 @@ fn start_devtools_resolve_node_command( ) -> Result, PendingDomCommandStartError> { let reference = command.reference; let top_frame_id = top_frame_id_for_owner(conn, owner); - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); if let DevToolsDomNodeReference::FrontendNodeId(frontend_node_id) = reference { return start_document_frontend_node_binding_command( conn, @@ -2301,16 +2254,9 @@ fn start_dom_object_reference_operation( operation: PendingDomObjectReferenceOperation, ) -> Result, PendingDomCommandStartError> { let reference = dom_object_reference_id_for_owner(conn, owner, &object_id); - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); - let include_whitespace = dom_agent_includes_whitespace_for_route( - conn, - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); + let include_whitespace = dom_agent_includes_whitespace_for_owner(conn, owner); let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let object_id = reference; @@ -2424,11 +2370,8 @@ fn start_devtools_push_nodes_by_backend_ids_command( owner: &CommandOwnerScope, command: DevToolsPushNodesByBackendIdsCommand, ) -> Result, PendingDomCommandStartError> { - let renderer_runtime_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_runtime_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let renderer_backend_positions = (0..command.backend_node_ids.len()).collect::>(); @@ -2513,16 +2456,9 @@ fn complete_pending_dom_command( }; let CompletedDomCommandWork::Page(completion) = completed_work; let completion = *completion; - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - session_id, - owner_scope.session_owner_route(), - ); - let include_whitespace = dom_agent_includes_whitespace_for_route( - conn, - session_id, - owner_scope.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(&owner_scope); + let include_whitespace = dom_agent_includes_whitespace_for_owner(conn, &owner_scope); let kind = match completed.kind { PendingDomCommandKind::PerformSearchLive => { @@ -3214,17 +3150,9 @@ fn complete_pending_dom_command_result( completed: CompletedDomCommandDispatch, ) -> DevToolsDomCommandTaskStep { let owner_scope = completed.owner_scope.clone(); - let session_id = owner_scope.session_id(); - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - session_id, - owner_scope.session_owner_route(), - ); - let include_whitespace = dom_agent_includes_whitespace_for_route( - conn, - session_id, - owner_scope.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(&owner_scope); + let include_whitespace = dom_agent_includes_whitespace_for_owner(conn, &owner_scope); let completed_work = match completed.completed { Ok(completion) => completion, Err(error) => { @@ -4335,16 +4263,9 @@ fn complete_frontend_node_binding_for_describe_node( top_frame_id: Option, out: &mut DomCommandOutput, ) -> DomCommandTaskStep { - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); - let include_whitespace = dom_agent_includes_whitespace_for_route( - conn, - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); + let include_whitespace = dom_agent_includes_whitespace_for_owner(conn, owner); complete_frontend_node_binding_followup( conn, command_id, @@ -4383,16 +4304,9 @@ fn complete_frontend_node_binding_for_describe_node_result( pierce: bool, top_frame_id: Option, ) -> DevToolsDomCommandTaskStep { - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); - let include_whitespace = dom_agent_includes_whitespace_for_route( - conn, - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); + let include_whitespace = dom_agent_includes_whitespace_for_owner(conn, owner); complete_frontend_node_binding_followup_result( conn, command_id, @@ -4431,16 +4345,9 @@ fn complete_frontend_node_binding_for_request_child_nodes( top_frame_id: Option, out: &mut DomCommandOutput, ) -> DomCommandTaskStep { - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); - let include_whitespace = dom_agent_includes_whitespace_for_route( - conn, - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); + let include_whitespace = dom_agent_includes_whitespace_for_owner(conn, owner); complete_frontend_node_binding_followup( conn, command_id, @@ -4470,16 +4377,9 @@ fn complete_frontend_node_binding_for_request_child_nodes_result( pierce: bool, top_frame_id: Option, ) -> DevToolsDomCommandTaskStep { - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); - let include_whitespace = dom_agent_includes_whitespace_for_route( - conn, - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); + let include_whitespace = dom_agent_includes_whitespace_for_owner(conn, owner); complete_frontend_node_binding_followup_result( conn, command_id, @@ -4510,16 +4410,9 @@ fn complete_frontend_node_binding_for_query_selector( top_frame_id: Option, out: &mut DomCommandOutput, ) -> DomCommandTaskStep { - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); - let include_whitespace = dom_agent_includes_whitespace_for_route( - conn, - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); + let include_whitespace = dom_agent_includes_whitespace_for_owner(conn, owner); complete_frontend_node_binding_followup( conn, command_id, @@ -4549,16 +4442,9 @@ fn complete_frontend_node_binding_for_query_selector_result( selector: String, multiple: bool, ) -> DevToolsDomCommandTaskStep { - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); - let include_whitespace = dom_agent_includes_whitespace_for_route( - conn, - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); + let include_whitespace = dom_agent_includes_whitespace_for_owner(conn, owner); complete_frontend_node_binding_followup_result( conn, command_id, @@ -4614,11 +4500,8 @@ fn complete_frontend_node_binding_for_resolve_node( top_frame_id: Option, out: &mut DomCommandOutput, ) -> DomCommandTaskStep { - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); complete_frontend_node_binding_followup( conn, command_id, @@ -4649,11 +4532,8 @@ fn complete_frontend_node_binding_for_resolve_node_result( object_group: Option, top_frame_id: Option, ) -> DevToolsDomCommandTaskStep { - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); complete_frontend_node_binding_followup_result( conn, command_id, @@ -5780,11 +5660,8 @@ fn start_document_frontend_node_binding_command( frontend_node_id: u32, kind: PendingDomCommandKind, ) -> Result, PendingDomCommandStartError> { - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let pending = page @@ -5932,28 +5809,30 @@ pub(crate) async fn execute_devtools_dom_command_async( conn: &mut CdpConnection, command: DevToolsCommand, ) -> Result { - let (target_id, command_session_id) = devtools_dom_command_route(&command)?; - let owner = if let Some(target_id) = target_id.as_deref() { - if conn.target_session_route_for_target_id(target_id).is_none() { - let result = super::child_frame::execute_devtools_dom_command(conn, target_id, command) + let context = devtools_dom_command_context(&command)?; + let target_id = context + .target_id + .as_ref() + .map(|target_id| target_id.to_string()); + let owner = conn + .command_owner_scope_for_devtools_context(context) + .ok_or_else(|| DevToolsError::new(DevToolsErrorKind::NoSuchTarget, "NoSuchTarget"))?; + if let Some(target_id) = target_id.as_deref() + && conn.target_session_route_for_target_id(target_id).is_none() + { + let result = + super::child_frame::execute_devtools_dom_command(conn, target_id, &owner, command) .await .map_err(DevToolsError::from)?; - return Ok(result); - } - let route = conn - .target_session_route_for_target_id(target_id) - .ok_or_else(|| DevToolsError::new(DevToolsErrorKind::NoSuchTarget, "NoSuchTarget"))?; - CommandOwnerScope::for_route(route) - } else { - CommandOwnerScope::capture(conn, command_session_id.as_deref()) - }; + return Ok(result); + } execute_devtools_dom_command_for_owner(conn, &owner, command).await } -fn devtools_dom_command_route( +fn devtools_dom_command_context( command: &DevToolsCommand, -) -> Result<(Option, Option), DevToolsError> { +) -> Result<&crate::devtools_runtime::DevToolsCommandContext, DevToolsError> { let context = match command { DevToolsCommand::QuerySelector(command) => &command.context, DevToolsCommand::GetAttributes(command) => &command.context, @@ -5983,16 +5862,7 @@ fn devtools_dom_command_route( )); } }; - Ok(( - context - .target_id - .as_ref() - .map(|target_id| target_id.to_string()), - context - .session_id - .as_ref() - .map(|session_id| session_id.to_string()), - )) + Ok(context) } async fn execute_devtools_dom_command_for_owner( diff --git a/moli-protocol/src/domains/dom/search.rs b/moli-protocol/src/domains/dom/search.rs index b62f6d4c6d..dab5800e17 100644 --- a/moli-protocol/src/domains/dom/search.rs +++ b/moli-protocol/src/domains/dom/search.rs @@ -83,16 +83,9 @@ pub(super) fn start_devtools_perform_search_command( owner: &CommandOwnerScope, command: DevToolsPerformSearchCommand, ) -> Result, PendingDomCommandStartError> { - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); - let include_whitespace = super::dom_agent_includes_whitespace_for_route( - conn, - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); + let include_whitespace = super::dom_agent_includes_whitespace_for_owner(conn, owner); let Some(page) = super::loaded_page_mut_for_owner(conn, owner) else { return Ok(None); }; @@ -119,11 +112,8 @@ pub(super) fn start_devtools_get_search_results_command( owner: &CommandOwnerScope, command: DevToolsGetSearchResultsCommand, ) -> Result, PendingDomCommandStartError> { - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); let Some(page) = super::loaded_page_mut_for_owner(conn, owner) else { return Ok(None); }; @@ -149,11 +139,8 @@ pub(super) fn start_devtools_discard_search_results_command( owner: &CommandOwnerScope, command: DevToolsDiscardSearchResultsCommand, ) -> Result, PendingDomCommandStartError> { - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); let Some(page) = super::loaded_page_mut_for_owner(conn, owner) else { return Ok(None); }; diff --git a/moli-protocol/src/domains/dom/set_file_input.rs b/moli-protocol/src/domains/dom/set_file_input.rs index f76ad59187..952856d49a 100644 --- a/moli-protocol/src/domains/dom/set_file_input.rs +++ b/moli-protocol/src/domains/dom/set_file_input.rs @@ -101,11 +101,8 @@ pub(super) fn start_devtools_set_file_input_files_command( ) -> Result, PendingDomCommandStartError> { let is_shared_node_id = is_webdriver_bidi_node_shared_id(command.object_id.as_str()); if is_shared_node_id { - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let pending = page @@ -424,11 +421,8 @@ fn start_set_file_input_files_frontend_node_binding( file_paths: Vec, append: bool, ) -> Result, PendingDomCommandStartError> { - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let pending = page @@ -455,11 +449,8 @@ fn start_set_file_input_files_for_remote_reference( append: bool, ) -> Result { let reference = dom_object_reference_id_for_owner(conn, owner, &object_id); - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); let page = loaded_page_mut_for_owner(conn, owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let object_id = reference; diff --git a/moli-protocol/src/domains/dom/stack_traces.rs b/moli-protocol/src/domains/dom/stack_traces.rs index 7d5249ca3b..989ac3e70e 100644 --- a/moli-protocol/src/domains/dom/stack_traces.rs +++ b/moli-protocol/src/domains/dom/stack_traces.rs @@ -28,11 +28,8 @@ pub(super) fn start_set_node_stack_traces_enabled_command( Ok(Some(params)) => params, _ => return Err(PendingDomCommandStartError::invalid_params()), }; - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(&owner); let page = super::loaded_page_mut_for_owner(conn, &owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let pending = page @@ -55,11 +52,8 @@ pub(super) fn start_get_node_stack_traces_command( Ok(Some(params)) => params, _ => return Err(PendingDomCommandStartError::invalid_params()), }; - let renderer_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(&owner); let page = super::loaded_page_mut_for_owner(conn, &owner) .ok_or_else(PendingDomCommandStartError::no_document_loaded)?; let pending = page diff --git a/moli-protocol/src/domains/dom_debugger.rs b/moli-protocol/src/domains/dom_debugger.rs index 8e9b073783..4fa546686b 100644 --- a/moli-protocol/src/domains/dom_debugger.rs +++ b/moli-protocol/src/domains/dom_debugger.rs @@ -244,18 +244,14 @@ pub(crate) fn complete_pending_dom_debugger_command( completed: CompletedDomDebuggerCommandDispatch, ) -> CommandOutputPlan { let session_id = completed.owner_scope.session_id().map(str::to_owned); - let owner_route = completed.owner_scope.session_owner_route(); match completed.operation { CompletedDomDebuggerOperation::GetEventListeners => { let resolution = completed.completed.and_then(|completion| { - conn.loaded_page_mut_for_protocol_access_for_route( - session_id.as_deref(), - owner_route, - ) - .and_then(|page| { - page.finish_dom_debugger_get_event_listeners(completion) - .map_err(|error| error.to_string()) - }) + conn.loaded_page_mut_for_protocol_access_for_owner(&completed.owner_scope) + .and_then(|page| { + page.finish_dom_debugger_get_event_listeners(completion) + .map_err(|error| error.to_string()) + }) }); match resolution { Ok(RendererDomDebuggerEventListenersResolution::Found(listeners)) => { @@ -272,17 +268,14 @@ pub(crate) fn complete_pending_dom_debugger_command( enabled, } => { let completion = completed.completed.and_then(|completion| { - conn.loaded_page_mut_for_protocol_access_for_route( - session_id.as_deref(), - owner_route, - ) - .and_then(|page| { - page.finish_unit_runtime_page_command( - completion, - "DOMDebugger event listener breakpoint", - ) - .map_err(|error| error.to_string()) - }) + conn.loaded_page_mut_for_protocol_access_for_owner(&completed.owner_scope) + .and_then(|page| { + page.finish_unit_runtime_page_command( + completion, + "DOMDebugger event listener breakpoint", + ) + .map_err(|error| error.to_string()) + }) }); if let Err(message) = completion { return CommandOutputPlan::error(-32000, message); @@ -311,14 +304,14 @@ pub(crate) fn complete_pending_dom_debugger_command( enabled, } => { let completion = completed.completed.and_then(|completion| { - conn.loaded_page_mut_for_protocol_access_for_route( - session_id.as_deref(), - owner_route, - ) - .and_then(|page| { - page.finish_unit_runtime_page_command(completion, "DOMDebugger XHR breakpoint") + conn.loaded_page_mut_for_protocol_access_for_owner(&completed.owner_scope) + .and_then(|page| { + page.finish_unit_runtime_page_command( + completion, + "DOMDebugger XHR breakpoint", + ) .map_err(|error| error.to_string()) - }) + }) }); if let Err(message) = completion { return CommandOutputPlan::error(-32000, message); @@ -340,14 +333,11 @@ pub(crate) fn complete_pending_dom_debugger_command( } CompletedDomDebuggerOperation::ConfigureDomBreakpoint => { let resolution = completed.completed.and_then(|completion| { - conn.loaded_page_mut_for_protocol_access_for_route( - session_id.as_deref(), - owner_route, - ) - .and_then(|page| { - page.finish_dom_debugger_configure_dom_breakpoint(completion) - .map_err(|error| error.to_string()) - }) + conn.loaded_page_mut_for_protocol_access_for_owner(&completed.owner_scope) + .and_then(|page| { + page.finish_dom_debugger_configure_dom_breakpoint(completion) + .map_err(|error| error.to_string()) + }) }); match resolution { Ok(RendererDomDebuggerDomBreakpointResolution::Configured) => { diff --git a/moli-protocol/src/domains/dom_snapshot.rs b/moli-protocol/src/domains/dom_snapshot.rs index 954f8a853d..83b042c896 100644 --- a/moli-protocol/src/domains/dom_snapshot.rs +++ b/moli-protocol/src/domains/dom_snapshot.rs @@ -148,10 +148,8 @@ pub(crate) fn complete_pending_dom_snapshot_command( conn: &mut CdpConnection, completed: CompletedDomSnapshotCommandDispatch, ) -> DomSnapshotCommandDispatchStep { - let session_id = completed.owner_scope.session_id(); - let owner_route = completed.owner_scope.session_owner_route(); let Some(page) = conn - .loaded_page_mut_for_protocol_access_for_route(session_id, owner_route) + .loaded_page_mut_for_protocol_access_for_owner(&completed.owner_scope) .ok() else { return DomSnapshotCommandDispatchStep::Complete(CommandOutputPlan::error( diff --git a/moli-protocol/src/domains/dom_storage/activity.rs b/moli-protocol/src/domains/dom_storage/activity.rs index 1ae1787278..9ecbedaeec 100644 --- a/moli-protocol/src/domains/dom_storage/activity.rs +++ b/moli-protocol/src/domains/dom_storage/activity.rs @@ -77,9 +77,7 @@ fn dom_storage_subscriptions_for_browser_context_owner( conn: &CdpConnection, owner: &CommandOwnerScope, ) -> Vec<(Option, WebStorageMutationSubscription)> { - let Some((browser_context_id, _)) = - conn.target_owner_identity_for_route(owner.session_id(), owner.session_owner_route()) - else { + let Some((browser_context_id, _)) = conn.target_owner_identity_for_owner(owner) else { return dom_storage_subscriptions_for_owner(conn, owner); }; let Some(browser_context) = conn.browser_context_by_id(&browser_context_id) else { @@ -116,7 +114,7 @@ fn dom_storage_subscriptions_for_owner( conn: &CdpConnection, owner: &CommandOwnerScope, ) -> Vec<(Option, WebStorageMutationSubscription)> { - conn.page_event_session_ids_for_route(owner.session_id(), owner.session_owner_route()) + conn.page_event_session_ids_for_owner(owner) .into_iter() .filter_map(|event_session_id| { let subscription = conn diff --git a/moli-protocol/src/domains/dom_storage/commands.rs b/moli-protocol/src/domains/dom_storage/commands.rs index bc91d7c918..c2920ab5d8 100644 --- a/moli-protocol/src/domains/dom_storage/commands.rs +++ b/moli-protocol/src/domains/dom_storage/commands.rs @@ -6,9 +6,7 @@ use serde_json::json; use url::Url; use crate::{ - conn::{ - BrowserContextPageStorageHandles, CdpConnection, CdpSessionRoute, Cmd, CommandOwnerScope, - }, + conn::{BrowserContextPageStorageHandles, CdpConnection, Cmd, CommandOwnerScope}, domains::{actions::DomStorageAction, command_output::CommandOutputPlan}, }; @@ -202,11 +200,7 @@ fn start_storage_operation( operation: DomStorageOperation, ) -> DomStorageCommandTaskStep { let owner_scope = CommandOwnerScope::capture(conn, cmd.session_id); - if let Err(plan) = storage_handles_for_route( - conn, - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) { + if let Err(plan) = storage_handles_for_owner(conn, &owner_scope) { return DomStorageCommandTaskStep::Complete(plan); } @@ -216,18 +210,14 @@ fn start_storage_operation( { return DomStorageCommandTaskStep::Complete(complete_storage_operation( conn, - cmd.session_id, - owner_scope.session_owner_route(), + &owner_scope, storage_id, operation, &storage_key, )); } - if let Ok(page) = conn.loaded_page_mut_for_protocol_access_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) { + if let Ok(page) = conn.loaded_page_mut_for_protocol_access_for_owner(&owner_scope) { return match page.start_document_storage_key_snapshot() { Ok(pending) => { DomStorageCommandTaskStep::Pending(Box::new(PendingDomStorageCommandDispatch { @@ -257,8 +247,7 @@ fn start_storage_operation( }; DomStorageCommandTaskStep::Complete(complete_storage_operation( conn, - cmd.session_id, - owner_scope.session_owner_route(), + &owner_scope, storage_id, operation, &storage_key, @@ -313,10 +302,7 @@ fn complete_top_frame_resolution( } }; let storage_key = { - let Ok(page) = conn.loaded_page_mut_for_protocol_access_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) else { + let Ok(page) = conn.loaded_page_mut_for_protocol_access_for_owner(&owner_scope) else { return DomStorageCommandTaskStep::Complete(frame_not_found_plan()); }; match page.finish_document_storage_key_snapshot(completion) { @@ -333,8 +319,7 @@ fn complete_top_frame_resolution( if storage_id_matches_key(&storage_id, &storage_key) { return DomStorageCommandTaskStep::Complete(complete_storage_operation( conn, - owner_scope.session_id(), - owner_scope.session_owner_route(), + &owner_scope, storage_id, operation, &storage_key, @@ -342,10 +327,7 @@ fn complete_top_frame_resolution( } let child_pending = { - let Ok(page) = conn.loaded_page_mut_for_protocol_access_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) else { + let Ok(page) = conn.loaded_page_mut_for_protocol_access_for_owner(&owner_scope) else { return DomStorageCommandTaskStep::Complete(frame_not_found_plan()); }; page.start_child_frame_tree_snapshot() @@ -383,10 +365,7 @@ fn complete_child_frame_resolution( } }; let child_frames = { - let Ok(page) = conn.loaded_page_mut_for_protocol_access_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) else { + let Ok(page) = conn.loaded_page_mut_for_protocol_access_for_owner(&owner_scope) else { return DomStorageCommandTaskStep::Complete(frame_not_found_plan()); }; match page.finish_child_frame_tree_snapshot(completion) { @@ -404,8 +383,7 @@ fn complete_child_frame_resolution( }; DomStorageCommandTaskStep::Complete(complete_storage_operation( conn, - owner_scope.session_id(), - owner_scope.session_owner_route(), + &owner_scope, storage_id, operation, &storage_key, @@ -414,8 +392,7 @@ fn complete_child_frame_resolution( fn complete_storage_operation( conn: &CdpConnection, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, storage_id: DomStorageId, operation: DomStorageOperation, storage_key: &str, @@ -423,7 +400,7 @@ fn complete_storage_operation( if !storage_id_matches_key(&storage_id, storage_key) { return frame_not_found_plan(); } - let handles = match storage_handles_for_route(conn, session_id, owner_route) { + let handles = match storage_handles_for_owner(conn, owner) { Ok(handles) => handles, Err(plan) => return plan, }; @@ -470,16 +447,15 @@ fn storage_handles_for_session_owner( conn: &CdpConnection, session_id: Option<&str>, ) -> Result { - storage_handles_for_route(conn, session_id, None) + let owner = CommandOwnerScope::capture(conn, session_id); + storage_handles_for_owner(conn, &owner) } -fn storage_handles_for_route( +fn storage_handles_for_owner( conn: &CdpConnection, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Result { - let Some((browser_context_id, Some(target_id))) = - conn.target_owner_identity_for_route(session_id, owner_route) + let Some((browser_context_id, Some(target_id))) = conn.target_owner_identity_for_owner(owner) else { return Err(CommandOutputPlan::error( -32000, diff --git a/moli-protocol/src/domains/emulation.rs b/moli-protocol/src/domains/emulation.rs index 8b4744669d..6836589a87 100644 --- a/moli-protocol/src/domains/emulation.rs +++ b/moli-protocol/src/domains/emulation.rs @@ -857,7 +857,8 @@ fn start_device_metrics_override_command( screen_width: Some(screen_width), screen_height: Some(screen_height), }; - match start_devtools_set_viewport_command(conn, cmd.id, command, None) { + let owner = CommandOwnerScope::capture(conn, cmd.session_id); + match start_devtools_set_viewport_command(conn, cmd.id, command, owner) { Ok(Some(pending)) => EmulationCommandTaskStep::Pending(pending), Ok(None) => EmulationCommandTaskStep::Complete(CommandOutputPlan::success()), Err(error) => { @@ -937,27 +938,18 @@ fn start_devtools_set_viewport_command( conn: &mut CdpConnection, command_id: Option, command: DevToolsSetViewportCommand, - owner_route: Option<&CdpSessionRoute>, + owner_scope: CommandOwnerScope, ) -> Result, DevToolsError> { - let owner_scope = CommandOwnerScope::capture_for_route( - conn, - command.context.session_id.as_ref().map(|id| id.as_str()), - owner_route, - ); - let session_id = owner_scope.session_id(); - let owner_route = owner_scope.session_owner_route(); if conn.browser_context.is_none() - && conn - .target_owner_identity_for_route(session_id, owner_route) - .is_none() + && conn.target_owner_identity_for_owner(&owner_scope).is_none() { return Ok(None); } - let metrics = set_viewport_metrics_from_command(conn, session_id, owner_route, &command)?; + let metrics = set_viewport_metrics_from_command(conn, &owner_scope, &command)?; let had_existing_device_metrics = conn - .target_session_owner_emulated_device_metrics_for_route(session_id, owner_route) + .target_session_owner_emulated_device_metrics_for_owner(&owner_scope) .is_some(); - if !conn.mutate_emulation_session_state_for_route(session_id, owner_route, |state| { + if !conn.mutate_emulation_session_state_for_owner(&owner_scope, |state| { if let Some(state) = state { *state.emulated_device_metrics = Some(metrics.clone()); } @@ -969,12 +961,12 @@ fn start_devtools_set_viewport_command( } let runtime_call_id = conn.next_internal_runtime_command_id(); let Some(page) = conn - .loaded_page_mut_for_target_configuration_for_route(session_id, owner_route) + .loaded_page_mut_for_target_configuration_for_owner(&owner_scope) .ok() else { return Ok(None); }; - let session_id = session_id.map(str::to_owned); + let session_id = owner_scope.session_id().map(str::to_owned); let viewport_surface = Some(metrics.viewport_surface().to_page_viewport_surface()); let pending_viewport = page .start_set_viewport_surface(viewport_surface) @@ -1008,12 +1000,10 @@ fn start_devtools_set_viewport_command( fn set_viewport_metrics_from_command( conn: &CdpConnection, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, command: &DevToolsSetViewportCommand, ) -> Result { - let current_metrics = - conn.target_session_owner_emulated_device_metrics_for_route(session_id, owner_route); + let current_metrics = conn.target_session_owner_emulated_device_metrics_for_owner(owner); set_viewport_metrics_from_current(current_metrics.as_ref(), command) } @@ -1263,7 +1253,8 @@ fn start_geolocation_override_for_current_route( route: &CdpSessionRoute, override_state: Option, ) -> Result, DevToolsError> { - if !conn.mutate_emulation_session_state_for_route(None, Some(route), |state| { + let owner = CommandOwnerScope::for_route(route.clone()); + if !conn.mutate_emulation_session_state_for_owner(&owner, |state| { if let Some(state) = state { *state.geolocation_override = override_state; } @@ -1349,7 +1340,8 @@ fn start_network_conditions_for_current_route( route: &CdpSessionRoute, network_conditions: Option, ) -> Result, DevToolsError> { - if !conn.mutate_emulation_session_state_for_route(None, Some(route), |state| { + let owner = CommandOwnerScope::for_route(route.clone()); + if !conn.mutate_emulation_session_state_for_owner(&owner, |state| { if let Some(state) = state { *state.network_conditions = network_conditions.map(emulated_network_conditions); } @@ -1377,10 +1369,10 @@ fn start_network_conditions_update_for_current_route( }), PendingEmulationPageTarget::SessionOwner { .. } => false, }; + let owner = CommandOwnerScope::for_route(route.clone()); let network_update = conn - .start_set_emulated_network_conditions_for_route( - None, - Some(route), + .start_set_emulated_network_conditions_for_owner( + &owner, effective_offline, 0.0, -1.0, @@ -1410,8 +1402,9 @@ fn start_extra_headers_for_current_route( headers: Vec<(String, String)>, ) -> Result, DevToolsError> { let target = pending_emulation_target_for_route(conn, route)?; + let owner = CommandOwnerScope::for_route(route.clone()); let pending = conn - .start_set_target_extra_http_headers_for_route(None, Some(route), headers) + .start_set_target_extra_http_headers_for_owner(&owner, headers) .map_err(devtools_emulation_owner_error)?; Ok(pending .map(|pending| { @@ -1482,10 +1475,7 @@ fn loaded_page_mut_for_pending_emulation_target<'a>( .and_then(|target| target.loaded_page_mut()) .map(|page| &*page), PendingEmulationPageTarget::SessionOwner { owner_scope } => conn - .loaded_page_mut_for_target_configuration_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) + .loaded_page_mut_for_target_configuration_for_owner(owner_scope) .ok() .map(|page| &*page), } @@ -1648,8 +1638,9 @@ fn start_user_agent_override_for_current_route( user_agent: Option, ) -> Result, DevToolsError> { let target = pending_emulation_target_for_route(conn, route)?; + let owner = CommandOwnerScope::for_route(route.clone()); let pending = conn - .start_set_base_user_agent_override_for_route(None, Some(route), user_agent) + .start_set_base_user_agent_override_for_owner(&owner, user_agent) .map_err(devtools_emulation_owner_error)?; if let Some(pending) = pending { return Ok(Some(PendingEmulationPageCommand { @@ -1667,12 +1658,13 @@ fn start_user_agent_loader_update_for_current_route( route: &CdpSessionRoute, ) -> Result, DevToolsError> { let target = pending_emulation_target_for_route(conn, route)?; - let load_inputs = conn.navigation_load_inputs_for_route(None, Some(route)); + let owner = CommandOwnerScope::for_route(route.clone()); + let load_inputs = conn.navigation_load_inputs_for_owner(&owner); let resource_runtime = conn .build_registered_browser_resource_runtime_for_navigation_load_inputs(&load_inputs) .map_err(|error| DevToolsError::new(DevToolsErrorKind::Internal, error))?; let Some(page) = conn - .loaded_page_mut_for_target_configuration_for_route(None, Some(route)) + .loaded_page_mut_for_target_configuration_for_owner(&owner) .ok() else { return Ok(None); @@ -1757,7 +1749,8 @@ fn start_locale_override_for_current_route( route: &CdpSessionRoute, locale: Option, ) -> Result, DevToolsError> { - if !conn.set_base_locale_override_for_route(None, Some(route), locale) { + let owner = CommandOwnerScope::for_route(route.clone()); + if !conn.set_base_locale_override_for_owner(&owner, locale) { return Err(devtools_emulation_owner_error( "BrowserContextNotLoaded".to_owned(), )); @@ -1774,11 +1767,12 @@ fn start_locale_update_for_current_route( pending.push(identity_update); } let target = pending_emulation_target_for_route(conn, route)?; - let Some(locale_override) = locale_override_for_route(conn, None, Some(route)) else { + let owner = CommandOwnerScope::for_route(route.clone()); + let Some(locale_override) = locale_override_for_owner(conn, &owner) else { return Ok(pending); }; let Some(page) = conn - .loaded_page_mut_for_target_configuration_for_route(None, Some(route)) + .loaded_page_mut_for_target_configuration_for_owner(&owner) .ok() else { return Ok(pending); @@ -1863,7 +1857,8 @@ fn start_timezone_override_for_current_route( route: &CdpSessionRoute, timezone: Option, ) -> Result, DevToolsError> { - if !conn.set_base_timezone_override_for_route(None, Some(route), timezone) { + let owner = CommandOwnerScope::for_route(route.clone()); + if !conn.set_base_timezone_override_for_owner(&owner, timezone) { return Err(devtools_emulation_owner_error( "BrowserContextNotLoaded".to_owned(), )); @@ -1876,9 +1871,10 @@ fn start_timezone_update_for_current_route( route: &CdpSessionRoute, ) -> Result, DevToolsError> { let target = pending_emulation_target_for_route(conn, route)?; - let load_inputs = conn.navigation_load_inputs_for_route(None, Some(route)); + let owner = CommandOwnerScope::for_route(route.clone()); + let load_inputs = conn.navigation_load_inputs_for_owner(&owner); let Some(page) = conn - .loaded_page_mut_for_target_configuration_for_route(None, Some(route)) + .loaded_page_mut_for_target_configuration_for_owner(&owner) .ok() else { return Ok(None); @@ -2033,7 +2029,12 @@ async fn execute_devtools_set_viewport_command_async( }; let mut command = command; command.context.session_id = None; - return match start_devtools_set_viewport_command(conn, None, command, Some(&route)) { + return match start_devtools_set_viewport_command( + conn, + None, + command, + CommandOwnerScope::for_route(route), + ) { Ok(Some(pending)) => { let completed = pending.wait().await; complete_pending_devtools_emulation_command(conn, completed) @@ -2042,7 +2043,11 @@ async fn execute_devtools_set_viewport_command_async( Err(error) => Err(error), }; } - match start_devtools_set_viewport_command(conn, None, command, None) { + let owner = CommandOwnerScope::capture( + conn, + command.context.session_id.as_ref().map(|id| id.as_str()), + ); + match start_devtools_set_viewport_command(conn, None, command, owner) { Ok(Some(pending)) => { let completed = pending.wait().await; complete_pending_devtools_emulation_command(conn, completed) @@ -2064,21 +2069,28 @@ async fn execute_devtools_set_window_state_command_async( )?; let mut command = command; command.context.session_id = None; - return execute_devtools_set_window_state_for_current_route(conn, command, Some(&route)) - .await; + return execute_devtools_set_window_state_for_owner( + conn, + command, + CommandOwnerScope::for_route(route), + ) + .await; } - execute_devtools_set_window_state_for_current_route(conn, command, None).await + let owner = CommandOwnerScope::capture( + conn, + command.context.session_id.as_ref().map(|id| id.as_str()), + ); + execute_devtools_set_window_state_for_owner(conn, command, owner).await } -async fn execute_devtools_set_window_state_for_current_route( +async fn execute_devtools_set_window_state_for_owner( conn: &mut CdpConnection, command: crate::devtools_runtime::DevToolsSetWindowStateCommand, - owner_route: Option<&CdpSessionRoute>, + owner: CommandOwnerScope, ) -> Result { - let session_id = command.context.session_id.as_ref().map(|id| id.as_str()); let state = target_window_surface_state_from_devtools(command.state); if conn - .with_target_owner_state_for_route_mut(session_id, owner_route, |owner_state| { + .with_target_owner_state_for_owner_mut(&owner, |owner_state| { owner_state.set_window_surface_state(state); }) .is_none() @@ -2088,9 +2100,8 @@ async fn execute_devtools_set_window_state_for_current_route( "BrowserContextNotLoaded", )); } - let pending = - start_session_surface_override_page_command_for_route(conn, session_id, owner_route) - .map_err(devtools_emulation_owner_error)?; + let pending = start_session_surface_override_page_command_for_owner(conn, &owner) + .map_err(devtools_emulation_owner_error)?; complete_emulation_page_updates(conn, devtools_command_session_id(&command.context), pending) .await } @@ -2105,19 +2116,20 @@ async fn execute_devtools_set_client_window_state_command_async( let mut window_state_context = command.context.clone(); window_state_context.session_id = None; window_state_context.target_id = Some(command.client_window.clone()); - let result = execute_devtools_set_window_state_for_current_route( + let result = execute_devtools_set_window_state_for_owner( conn, crate::devtools_runtime::DevToolsSetWindowStateCommand { context: window_state_context, state: command.state, }, - Some(&route), + CommandOwnerScope::for_route(route.clone()), ) .await; match result { Ok(_) => { - let _ = conn.with_target_owner_state_for_route_mut(None, Some(&route), |owner_state| { + let owner = CommandOwnerScope::for_route(route); + let _ = conn.with_target_owner_state_for_owner_mut(&owner, |owner_state| { owner_state.set_window_surface_geometry( command.width, command.height, @@ -2518,10 +2530,9 @@ fn pending_emulation_page_configuration_will_be_replayed( }; let current_attachment_id = match target { PendingEmulationPageTarget::SessionOwner { owner_scope } => { - let Some((browser_context_id, target_id)) = conn.target_owner_identity_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) else { + let Some((browser_context_id, target_id)) = + conn.target_owner_identity_for_owner(owner_scope) + else { return false; }; let Some(browser_context) = conn.browser_context_by_id(&browser_context_id) else { @@ -2749,20 +2760,17 @@ fn start_session_surface_override_page_command( conn: &mut CdpConnection, session_id: Option<&str>, ) -> Result, String> { - start_session_surface_override_page_command_for_route(conn, session_id, None) + let owner = CommandOwnerScope::capture(conn, session_id); + start_session_surface_override_page_command_for_owner(conn, &owner) } -fn start_session_surface_override_page_command_for_route( +fn start_session_surface_override_page_command_for_owner( conn: &mut CdpConnection, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner_scope: &CommandOwnerScope, ) -> Result, String> { - let owner_scope = CommandOwnerScope::capture_for_route(conn, session_id, owner_route); - let session_id = owner_scope.session_id(); - let owner_route = owner_scope.session_owner_route(); let script = { let Some((browser_context_id, target_id)) = - conn.target_owner_identity_for_route(session_id, owner_route) + conn.target_owner_identity_for_owner(owner_scope) else { return Err("BrowserContextNotLoaded".to_owned()); }; @@ -2782,13 +2790,15 @@ fn start_session_surface_override_page_command_for_route( }; let runtime_call_id = conn.next_internal_runtime_command_id(); let Some(page) = conn - .loaded_page_mut_for_target_configuration_for_route(session_id, owner_route) + .loaded_page_mut_for_target_configuration_for_owner(owner_scope) .ok() else { return Ok(Vec::new()); }; start_surface_override_page_command( - PendingEmulationPageTarget::SessionOwner { owner_scope }, + PendingEmulationPageTarget::SessionOwner { + owner_scope: owner_scope.clone(), + }, page, script, runtime_call_id, @@ -2816,19 +2826,16 @@ fn start_surface_override_for_route( } } PendingEmulationPageTarget::SessionOwner { owner_scope } => { - return start_session_surface_override_page_command_for_route( - conn, - owner_scope.session_id(), - owner_scope.session_owner_route(), - ); + return start_session_surface_override_page_command_for_owner(conn, owner_scope); } }; let Some(script) = script else { return Ok(Vec::new()); }; let runtime_call_id = conn.next_internal_runtime_command_id(); + let owner = CommandOwnerScope::for_route(route.clone()); let Some(page) = conn - .loaded_page_mut_for_target_configuration_for_route(None, Some(route)) + .loaded_page_mut_for_target_configuration_for_owner(&owner) .ok() else { return Ok(Vec::new()); @@ -2873,16 +2880,15 @@ fn locale_override_for_session( conn: &CdpConnection, session_id: Option<&str>, ) -> Option> { - locale_override_for_route(conn, session_id, None) + let owner = CommandOwnerScope::capture(conn, session_id); + locale_override_for_owner(conn, &owner) } -fn locale_override_for_route( +fn locale_override_for_owner( conn: &CdpConnection, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option> { - let (browser_context_id, target_id) = - conn.target_owner_identity_for_route(session_id, owner_route)?; + let (browser_context_id, target_id) = conn.target_owner_identity_for_owner(owner)?; let browser_context = conn.browser_context_by_id(&browser_context_id)?; if let Some(target_id) = target_id { return Some(browser_context.effective_locale_override_for_target_owned(&target_id)); @@ -2899,17 +2905,10 @@ fn finish_pending_emulation_page_command( match target { PendingEmulationPageTarget::SessionOwner { owner_scope } => { if matches!(operation, PendingEmulationPageOperation::SetUserAgentLoader) { - return conn.finish_rebuild_resource_runtime_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - completion, - ); + return conn.finish_rebuild_resource_runtime_for_owner(&owner_scope, completion); } let page = conn - .loaded_page_mut_for_target_configuration_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) + .loaded_page_mut_for_target_configuration_for_owner(&owner_scope) .ok(); finish_emulation_page_operation_on_current_attachment(page, operation, completion) } diff --git a/moli-protocol/src/domains/emulation/tests.rs b/moli-protocol/src/domains/emulation/tests.rs index a0ed064e60..3b364e4a0f 100644 --- a/moli-protocol/src/domains/emulation/tests.rs +++ b/moli-protocol/src/domains/emulation/tests.rs @@ -727,9 +727,8 @@ async fn idle_override_updates_idle_detector_and_clear_restores_actual_state() { })); ctx.conn - .start_document_navigation_for_route( - Some("SID-1"), - None, + .start_document_navigation_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), "LID-idle-cross-document".to_owned(), ) .expect("cross-Document navigation should enter the pending state"); diff --git a/moli-protocol/src/domains/fetch.rs b/moli-protocol/src/domains/fetch.rs index f575cff4db..9e479c1435 100644 --- a/moli-protocol/src/domains/fetch.rs +++ b/moli-protocol/src/domains/fetch.rs @@ -9,9 +9,8 @@ mod state; mod subresource; use crate::conn::{ - BackgroundProtocolEvent, CdpConnection, CdpSessionRoute, Cmd, CommandOwnerScope, - DevToolsCommandExecutionOutput, FetchInterceptionPattern, - FetchRequestStage as ConnFetchRequestStage, + BackgroundProtocolEvent, CdpConnection, Cmd, CommandOwnerScope, DevToolsCommandExecutionOutput, + FetchInterceptionPattern, FetchRequestStage as ConnFetchRequestStage, }; use crate::devtools_runtime::{ DevToolsAddNetworkInterceptCommand, DevToolsAddNetworkInterceptResult, DevToolsCommand, @@ -343,15 +342,10 @@ pub(crate) async fn execute_devtools_fetch_command_async_with_protocol_events( command: DevToolsCommand, ) -> DevToolsCommandExecutionOutput { let success_result = devtools_fetch_success_result(&command); - let (owner_session_id, owner_route) = match fetch_devtools_command_session_ids(conn, &command) { - Ok(session_ids) => session_ids, + let owner = match fetch_devtools_command_owner(conn, &command) { + Ok(owner) => owner, Err(error) => return DevToolsCommandExecutionOutput::new(Err(error)), }; - let owner = CommandOwnerScope::capture_for_route( - conn, - owner_session_id.as_deref(), - owner_route.as_ref(), - ); let step = start_devtools_fetch_command_for_owner(conn, None, &owner, command); match step { FetchCommandTaskStep::Complete(mut plan) => { @@ -414,66 +408,64 @@ fn start_devtools_fetch_command_for_owner( } } -fn fetch_devtools_command_session_ids( +fn fetch_devtools_command_owner( conn: &CdpConnection, command: &DevToolsCommand, -) -> Result<(Option, Option), DevToolsError> { +) -> Result { let (context, request_id) = match command { DevToolsCommand::AddNetworkIntercept(command) => { - return fetch_config_devtools_command_session_ids(conn, command.context.clone()); + return fetch_config_devtools_command_owner(conn, &command.context); } DevToolsCommand::RemoveNetworkIntercept(command) => { - return fetch_config_devtools_command_session_ids(conn, command.context.clone()); + return fetch_config_devtools_command_owner(conn, &command.context); } DevToolsCommand::ContinueInterceptedRequest(command) => { - (command.context.clone(), command.request_id.as_str()) + (&command.context, command.request_id.as_str()) } DevToolsCommand::ContinueInterceptedResponse(command) => { - (command.context.clone(), command.request_id.as_str()) + (&command.context, command.request_id.as_str()) } DevToolsCommand::ContinueWithAuth(command) => { - (command.context.clone(), command.request_id.as_str()) + (&command.context, command.request_id.as_str()) } DevToolsCommand::FailInterceptedRequest(command) => { - (command.context.clone(), command.request_id.as_str()) + (&command.context, command.request_id.as_str()) } DevToolsCommand::FulfillInterceptedRequest(command) => { - (command.context.clone(), command.request_id.as_str()) + (&command.context, command.request_id.as_str()) } - _ => return Ok((None, None)), + _ => return Ok(CommandOwnerScope::capture(conn, None)), }; - let response_session_id = context - .session_id - .as_ref() - .map(|session| session.as_str().to_owned()); if context.protocol == DevToolsProtocol::Cdp { - return Ok((response_session_id, None)); + return Ok(CommandOwnerScope::capture( + conn, + context.session_id.as_ref().map(|session| session.as_str()), + )); } - Ok((None, conn.pending_fetch_request_session_route(request_id))) + Ok(conn + .pending_fetch_request_session_route(request_id) + .map(CommandOwnerScope::for_route) + .unwrap_or_else(|| CommandOwnerScope::capture(conn, None))) } -fn fetch_config_devtools_command_session_ids( +fn fetch_config_devtools_command_owner( conn: &CdpConnection, - context: crate::devtools_runtime::DevToolsCommandContext, -) -> Result<(Option, Option), DevToolsError> { - let response_session_id = context - .session_id - .as_ref() - .map(|session| session.as_str().to_owned()); + context: &crate::devtools_runtime::DevToolsCommandContext, +) -> Result { if context.protocol == DevToolsProtocol::Cdp { - return Ok((response_session_id, None)); + return Ok(CommandOwnerScope::capture( + conn, + context.session_id.as_ref().map(|session| session.as_str()), + )); } - let owner_route = if let Some(target_id) = context.target_id.as_ref() { - Some( - conn.target_session_route_for_target_id(target_id.as_str()) - .ok_or_else(|| { - DevToolsError::new(DevToolsErrorKind::NoSuchTarget, "NoSuchTarget") - })?, - ) + if let Some(target_id) = context.target_id.as_ref() { + let route = conn + .target_session_route_for_target_id(target_id.as_str()) + .ok_or_else(|| DevToolsError::new(DevToolsErrorKind::NoSuchTarget, "NoSuchTarget"))?; + Ok(CommandOwnerScope::for_route(route)) } else { - None - }; - Ok((None, owner_route)) + Ok(CommandOwnerScope::capture(conn, None)) + } } fn start_enable_command(conn: &mut CdpConnection, cmd: &Cmd<'_>) -> FetchCommandTaskStep { @@ -535,9 +527,8 @@ fn start_devtools_add_network_intercept_command( .as_ref() .map(|session_id| session_id.as_str().to_owned()) }; - match conn.start_add_network_intercept_for_route( - owner.session_id(), - owner.session_owner_route(), + match conn.start_add_network_intercept_for_owner( + owner, intercept_session_id, command.intercept_id.as_str().to_owned(), handle_auth_requests, @@ -573,12 +564,7 @@ fn start_devtools_remove_network_intercept_command( intercept_id: &str, allow_global_lookup: bool, ) -> FetchCommandTaskStep { - match conn.start_remove_network_intercept_for_route( - owner.session_id(), - owner.session_owner_route(), - intercept_id, - allow_global_lookup, - ) { + match conn.start_remove_network_intercept_for_owner(owner, intercept_id, allow_global_lookup) { Ok(Some(pending)) => { FetchCommandTaskStep::Pending(PendingFetchCommandDispatch::new_for_owner( command_id, @@ -821,10 +807,7 @@ fn complete_fetch_config_update_command( Ok(completion) => completion, Err(error) => return CommandOutputPlan::error(-32000, error), }; - let page = match conn.loaded_page_mut_for_protocol_access_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) { + let page = match conn.loaded_page_mut_for_protocol_access_for_owner(&owner_scope) { Ok(page) => page, Err(message) if message == "NoDocumentLoaded" => { return CommandOutputPlan::from_devtools_result(result); @@ -881,10 +864,7 @@ async fn complete_disable_command_async( return; } }; - match conn.loaded_page_mut_for_protocol_access_for_route( - owner.session_id(), - owner.session_owner_route(), - ) { + match conn.loaded_page_mut_for_protocol_access_for_owner(owner) { Ok(page) => { if let Err(error) = page.finish_set_fetch_subresource_interception(completion) { out.push_error( @@ -956,9 +936,8 @@ async fn complete_disable_command_async( } for (_, pending) in pending_subresource_fetches { if let Ok(predecessor) = conn - .fail_pending_subresource_fetch_for_route_async( - owner.session_id(), - owner.session_owner_route(), + .fail_pending_subresource_fetch_for_owner_async( + owner, pending.internal_id, "Fetch interception disabled".to_owned(), ) @@ -980,9 +959,8 @@ async fn complete_disable_command_async( } for (_, pending) in pending_subresource_auths { if let Ok(predecessor) = conn - .fail_pending_subresource_auth_for_route_async( - owner.session_id(), - owner.session_owner_route(), + .fail_pending_subresource_auth_for_owner_async( + owner, pending.internal_id, "Fetch interception disabled".to_owned(), ) @@ -1004,9 +982,8 @@ async fn complete_disable_command_async( } for (_, pending) in pending_subresource_responses { if let Ok(predecessor) = conn - .fail_pending_subresource_response_for_route_async( - owner.session_id(), - owner.session_owner_route(), + .fail_pending_subresource_response_for_owner_async( + owner, pending.internal_id, "Fetch interception disabled".to_owned(), ) diff --git a/moli-protocol/src/domains/fetch/auth.rs b/moli-protocol/src/domains/fetch/auth.rs index f60a5148ce..c2b3d6c15e 100644 --- a/moli-protocol/src/domains/fetch/auth.rs +++ b/moli-protocol/src/domains/fetch/auth.rs @@ -168,11 +168,8 @@ pub(super) fn start_devtools_continue_with_auth_command_for_pending( ) { Some(correlation) => Some(correlation), None => { - conn.register_pending_subresource_fetch_auth_request_for_route( - command_session_id, - owner.session_owner_route(), - request_id, - pending, + conn.register_pending_subresource_fetch_auth_request_for_owner( + owner, request_id, pending, ); return Some(FetchCommandTaskStep::Complete( CommandOutputPlan::error(-32000, "RequestNotFound"), @@ -182,10 +179,7 @@ pub(super) fn start_devtools_continue_with_auth_command_for_pending( } else { None }; - let pending_page = match conn.loaded_page_mut_for_protocol_access_for_route( - command_session_id, - owner.session_owner_route(), - ) { + let pending_page = match conn.loaded_page_mut_for_protocol_access_for_owner(owner) { Ok(page) => (match command.action { DevToolsAuthChallengeAction::Default => page .start_fail_pending_subresource_auth( @@ -206,11 +200,8 @@ pub(super) fn start_devtools_continue_with_auth_command_for_pending( if let Some(correlation) = cancel_correlation { correlation.rollback(conn); } - conn.register_pending_subresource_fetch_auth_request_for_route( - command_session_id, - owner.session_owner_route(), - request_id, - pending, + conn.register_pending_subresource_fetch_auth_request_for_owner( + owner, request_id, pending, ); return Some(FetchCommandTaskStep::Complete(CommandOutputPlan::error( -32000, @@ -249,9 +240,8 @@ pub(super) fn start_devtools_continue_with_auth_command_for_pending( command.username.as_deref().unwrap_or_default(), command.password.as_deref().unwrap_or_default(), ) else { - conn.register_pending_subresource_fetch_auth_request_for_route( - command_session_id, - owner.session_owner_route(), + conn.register_pending_subresource_fetch_auth_request_for_owner( + owner, request_id.clone(), pending, ); @@ -270,11 +260,8 @@ pub(super) fn start_devtools_continue_with_auth_command_for_pending( ) { Some(correlation) => correlation, None => { - conn.register_pending_subresource_fetch_auth_request_for_route( - command_session_id, - owner.session_owner_route(), - request_id, - pending, + conn.register_pending_subresource_fetch_auth_request_for_owner( + owner, request_id, pending, ); return Some(FetchCommandTaskStep::Complete(CommandOutputPlan::error( -32000, @@ -282,10 +269,7 @@ pub(super) fn start_devtools_continue_with_auth_command_for_pending( ))); } }; - let pending_page = match conn.loaded_page_mut_for_protocol_access_for_route( - command_session_id, - owner.session_owner_route(), - ) { + let pending_page = match conn.loaded_page_mut_for_protocol_access_for_owner(owner) { Ok(page) => page .start_continue_pending_subresource_auth(pending.internal_id, auth) .map_err(|error| format!("subresource auth continue failed: {error}")), @@ -295,11 +279,8 @@ pub(super) fn start_devtools_continue_with_auth_command_for_pending( Ok(pending_page) => pending_page, Err(message) => { correlation.rollback(conn); - conn.register_pending_subresource_fetch_auth_request_for_route( - command_session_id, - owner.session_owner_route(), - request_id, - pending, + conn.register_pending_subresource_fetch_auth_request_for_owner( + owner, request_id, pending, ); return Some(FetchCommandTaskStep::Complete(CommandOutputPlan::error( -32000, message, @@ -371,9 +352,8 @@ pub(super) fn start_devtools_continue_with_auth_command_for_pending( command.username.as_deref().unwrap_or_default(), command.password.as_deref().unwrap_or_default(), ) else { - conn.register_pending_fetch_auth_navigation_for_route( - command_session_id, - owner.session_owner_route(), + conn.register_pending_fetch_auth_navigation_for_owner( + owner, request_id.clone(), pending, ); @@ -617,10 +597,9 @@ async fn complete_subresource_auth_terminal_async( out: &mut FetchCommandOutput, ) { let activity_session_id = pending.owner_session_id.as_deref().or(owner.session_id()); - let activity_owner_route = activity_session_id - .is_none() - .then(|| owner.session_owner_route()) - .flatten(); + let activity_owner = activity_session_id + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); let Some(completed) = completed else { if let Some(correlation) = correlation { correlation.rollback(conn); @@ -638,9 +617,7 @@ async fn complete_subresource_auth_terminal_async( return; } }; - let result = match conn - .loaded_page_mut_for_protocol_access_for_route(activity_session_id, activity_owner_route) - { + let result = match conn.loaded_page_mut_for_protocol_access_for_owner(&activity_owner) { Ok(page) if expose_challenged_response => page .finish_cancel_pending_subresource_auth(completion) .map(|_| ()), @@ -683,10 +660,7 @@ fn finish_continue_subresource_auth( completed: Option>, ) -> Result<(), String> { let completion = completed.ok_or_else(|| "Missing renderer completion".to_owned())??; - let page = conn.loaded_page_mut_for_protocol_access_for_route( - owner.session_id(), - owner.session_owner_route(), - )?; + let page = conn.loaded_page_mut_for_protocol_access_for_owner(owner)?; page.finish_continue_pending_subresource_auth(completion) .map(|_| ()) .map_err(|error| format!("subresource auth continue failed: {error}")) diff --git a/moli-protocol/src/domains/fetch/body_stream.rs b/moli-protocol/src/domains/fetch/body_stream.rs index 5de5adfb41..d262a4f163 100644 --- a/moli-protocol/src/domains/fetch/body_stream.rs +++ b/moli-protocol/src/domains/fetch/body_stream.rs @@ -30,11 +30,9 @@ pub(super) fn start_get_response_body_command( )); } }; - if let Some(transfer) = conn.take_pending_fetch_response_transfer_for_body_read_for_route( - owner.session_id(), - owner.session_owner_route(), - ¶ms.request_id, - ) { + if let Some(transfer) = conn + .take_pending_fetch_response_transfer_for_body_read_for_owner(&owner, ¶ms.request_id) + { return FetchCommandTaskStep::Pending(PendingFetchCommandDispatch::new_for_owner( cmd.id, owner, @@ -114,30 +112,19 @@ pub(super) fn complete_get_response_body_from_transfer( }; let plan = match *result { Ok((Some(bytes), transfer)) => { - conn.register_pending_fetch_response_transfer_for_route( - owner.session_id(), - owner.session_owner_route(), - request_id, - transfer, - ); + conn.register_pending_fetch_response_transfer_for_owner(owner, request_id, transfer); response_body_command_output_plan(bytes) } Ok((None, transfer)) => { - conn.register_pending_fetch_response_transfer_for_route( - owner.session_id(), - owner.session_owner_route(), + conn.register_pending_fetch_response_transfer_for_owner( + owner, request_id.clone(), transfer, ); get_response_body_without_transfer_command_output_plan(conn, owner, &request_id) } Err((message, transfer)) => { - conn.register_pending_fetch_response_transfer_for_route( - owner.session_id(), - owner.session_owner_route(), - request_id, - transfer, - ); + conn.register_pending_fetch_response_transfer_for_owner(owner, request_id, transfer); CommandOutputPlan::error(-32000, message) } }; diff --git a/moli-protocol/src/domains/fetch/commands.rs b/moli-protocol/src/domains/fetch/commands.rs index 440f56582f..323e759114 100644 --- a/moli-protocol/src/domains/fetch/commands.rs +++ b/moli-protocol/src/domains/fetch/commands.rs @@ -260,10 +260,7 @@ fn start_devtools_continue_intercepted_request_command( let headers = command.headers.clone().or(chain_headers); pending.request_stage_chain = None; let configured_response_stage = conn - .target_fetch_subresource_interception_snapshot_for_route( - command_session_id, - owner.session_owner_route(), - ) + .target_fetch_subresource_interception_snapshot_for_owner(owner) .is_some_and(|snapshot| { snapshot.has_response_stage_candidate(pending.resource_type.into()) }); @@ -277,10 +274,7 @@ fn start_devtools_continue_intercepted_request_command( } return FetchCommandTaskStep::Complete(CommandOutputPlan::success()); } - let handle_auth_requests = conn.target_fetch_handle_auth_requests_for_route( - command_session_id, - owner.session_owner_route(), - ); + let handle_auth_requests = conn.target_fetch_handle_auth_requests_for_owner(owner); let should_register = pending.resource_type != SubresourceResourceType::WebSocket || intercept_response; let correlation = match if configured_response_stage && !command.intercept_response { @@ -301,11 +295,8 @@ fn start_devtools_continue_intercepted_request_command( } { Some(correlation) => correlation, None => { - conn.register_pending_subresource_fetch_request_for_route( - command_session_id, - owner.session_owner_route(), - request_id, - pending, + conn.register_pending_subresource_fetch_request_for_owner( + owner, request_id, pending, ); return FetchCommandTaskStep::Complete(CommandOutputPlan::error( -32000, @@ -313,10 +304,7 @@ fn start_devtools_continue_intercepted_request_command( )); } }; - let pending_page = match conn.loaded_page_mut_for_protocol_access_for_route( - command_session_id, - owner.session_owner_route(), - ) { + let pending_page = match conn.loaded_page_mut_for_protocol_access_for_owner(owner) { Ok(page) => page .start_continue_pending_subresource_fetch( pending.internal_id, @@ -334,11 +322,8 @@ fn start_devtools_continue_intercepted_request_command( Ok(pending_page) => pending_page, Err(message) => { correlation.rollback(conn); - conn.register_pending_subresource_fetch_request_for_route( - command_session_id, - owner.session_owner_route(), - request_id, - pending, + conn.register_pending_subresource_fetch_request_for_owner( + owner, request_id, pending, ); return FetchCommandTaskStep::Complete(CommandOutputPlan::error(-32000, message)); } @@ -434,10 +419,7 @@ fn finish_continue_subresource_request( completed: Option>, ) -> Result<(), String> { let completion = completed.ok_or_else(|| "Missing renderer completion".to_owned())??; - let page = conn.loaded_page_mut_for_protocol_access_for_route( - owner.session_id(), - owner.session_owner_route(), - )?; + let page = conn.loaded_page_mut_for_protocol_access_for_owner(owner)?; page.finish_continue_pending_subresource_fetch(completion) .map(|_| ()) .map_err(|error| format!("subresource fetch continue failed: {error}")) @@ -546,10 +528,7 @@ fn start_devtools_fail_intercepted_request_command( let mut plan = CommandOutputPlan::success(); let mut events = Vec::new(); let loader_id = conn - .current_document_loader_id_for_route( - command_session_id, - owner.session_owner_route(), - ) + .current_document_loader_id_for_owner(owner) .unwrap_or_else(|| DEFAULT_LOADER_ID.to_owned()); network::emit_loading_failed( &mut events, @@ -564,10 +543,7 @@ fn start_devtools_fail_intercepted_request_command( plan.extend_background_events(events); return FetchCommandTaskStep::Complete(plan); } - let page = match conn.loaded_page_mut_for_protocol_access_for_route( - command_session_id, - owner.session_owner_route(), - ) { + let page = match conn.loaded_page_mut_for_protocol_access_for_owner(owner) { Ok(page) => page, Err(message) if message == "NoDocumentLoaded" => { return FetchCommandTaskStep::Complete(CommandOutputPlan::error( @@ -608,10 +584,7 @@ fn start_devtools_fail_intercepted_request_command( action_session_id, &request_id, ) { - let page = match conn.loaded_page_mut_for_protocol_access_for_route( - command_session_id, - owner.session_owner_route(), - ) { + let page = match conn.loaded_page_mut_for_protocol_access_for_owner(owner) { Ok(page) => page, Err(message) if message == "NoDocumentLoaded" => { return FetchCommandTaskStep::Complete(CommandOutputPlan::error( @@ -646,11 +619,9 @@ fn start_devtools_fail_intercepted_request_command( )); } - if let Some(transfer) = conn.take_pending_fetch_response_transfer_for_terminal_action_for_route( - command_session_id, - owner.session_owner_route(), - &request_id, - ) { + if let Some(transfer) = + conn.take_pending_fetch_response_transfer_for_terminal_action_for_owner(owner, &request_id) + { return FetchCommandTaskStep::Pending(PendingFetchCommandDispatch::new_for_owner( command_id, owner.clone(), @@ -712,10 +683,7 @@ pub(super) async fn complete_fail_request_command_async( return; } }; - match conn.loaded_page_mut_for_protocol_access_for_route( - owner.session_id(), - owner.session_owner_route(), - ) { + match conn.loaded_page_mut_for_protocol_access_for_owner(owner) { Ok(page) => { if let Err(error) = page.finish_fail_pending_subresource_fetch(completion) { out.push_error(-32000, format!("subresource fetch fail failed: {error}")); @@ -754,10 +722,7 @@ pub(super) async fn complete_fail_request_command_async( return; } }; - match conn.loaded_page_mut_for_protocol_access_for_route( - owner.session_id(), - owner.session_owner_route(), - ) { + match conn.loaded_page_mut_for_protocol_access_for_owner(owner) { Ok(page) => { if let Err(error) = page.finish_fail_pending_subresource_response(completion) { out.push_error( @@ -956,10 +921,7 @@ fn start_devtools_fulfill_intercepted_request_command( let websocket_socket_id = pending.websocket_socket_id; let register_synthetic_websocket = pending.resource_type == SubresourceResourceType::WebSocket && response_code == 101; - let page = match conn.loaded_page_mut_for_protocol_access_for_route( - command_session_id, - owner.session_owner_route(), - ) { + let page = match conn.loaded_page_mut_for_protocol_access_for_owner(owner) { Ok(page) => page, Err(message) if message == "NoDocumentLoaded" => { return FetchCommandTaskStep::Complete(CommandOutputPlan::error( @@ -1007,10 +969,7 @@ fn start_devtools_fulfill_intercepted_request_command( action_session_id, &request_id, ) { - let page = match conn.loaded_page_mut_for_protocol_access_for_route( - command_session_id, - owner.session_owner_route(), - ) { + let page = match conn.loaded_page_mut_for_protocol_access_for_owner(owner) { Ok(page) => page, Err(message) if message == "NoDocumentLoaded" => { return FetchCommandTaskStep::Complete(CommandOutputPlan::error( @@ -1064,11 +1023,9 @@ fn start_devtools_fulfill_intercepted_request_command( )); } - if let Some(transfer) = conn.take_pending_fetch_response_transfer_for_terminal_action_for_route( - command_session_id, - owner.session_owner_route(), - &request_id, - ) { + if let Some(transfer) = + conn.take_pending_fetch_response_transfer_for_terminal_action_for_owner(owner, &request_id) + { return FetchCommandTaskStep::Pending(PendingFetchCommandDispatch::new_for_owner( command_id, owner.clone(), @@ -1116,10 +1073,7 @@ pub(super) async fn complete_fulfill_request_command_async( return; } }; - match conn.loaded_page_mut_for_protocol_access_for_route( - owner.session_id(), - owner.session_owner_route(), - ) { + match conn.loaded_page_mut_for_protocol_access_for_owner(owner) { Ok(page) => { if let Err(error) = page.finish_fulfill_pending_subresource_fetch(completion) { out.push_error( @@ -1139,9 +1093,8 @@ pub(super) async fn complete_fulfill_request_command_async( } } if register_synthetic_websocket && let Some(socket_id) = websocket_socket_id { - conn.register_synthetic_websocket_request_for_route( - owner.session_id(), - owner.session_owner_route(), + conn.register_synthetic_websocket_request_for_owner( + owner, request_id, network_request_id, socket_id, @@ -1170,10 +1123,7 @@ pub(super) async fn complete_fulfill_request_command_async( return; } }; - match conn.loaded_page_mut_for_protocol_access_for_route( - owner.session_id(), - owner.session_owner_route(), - ) { + match conn.loaded_page_mut_for_protocol_access_for_owner(owner) { Ok(page) => { if let Err(error) = page.finish_fulfill_pending_subresource_response(completion) { @@ -1424,10 +1374,7 @@ pub(super) fn complete_websocket_page_command( return; } }; - let result = match conn.loaded_page_mut_for_protocol_access_for_route( - owner.session_id(), - owner.session_owner_route(), - ) { + let result = match conn.loaded_page_mut_for_protocol_access_for_owner(owner) { Ok(page) => match operation { PendingWebSocketCommandOperation::DispatchText => { page.finish_receive_synthetic_websocket_text(completion) @@ -1560,17 +1507,12 @@ fn start_devtools_continue_intercepted_response_command( command.context.protocol, command.context.session_id.as_ref(), ); - if let Some(transfer) = conn.take_pending_fetch_response_transfer_for_terminal_action_for_route( - command_session_id, - owner.session_owner_route(), - &request_id, - ) { + if let Some(transfer) = + conn.take_pending_fetch_response_transfer_for_terminal_action_for_owner(owner, &request_id) + { let _ = &command.response_phrase; let transfer_response_headers = response_headers.clone().unwrap_or_default(); - if let Some(sender) = conn.background_navigation_completion_sender_for_route( - command_session_id, - owner.session_owner_route(), - ) { + if let Some(sender) = conn.background_navigation_completion_sender_for_owner(owner) { match transfer.into_pending_streaming_document_response_navigation() { Ok(pending) => { // Chromium ACKs Fetch.continueResponse when the response-stage @@ -1627,11 +1569,8 @@ fn start_devtools_continue_intercepted_response_command( &request_id, ) { if pending.response_body_taken_as_stream { - conn.register_pending_subresource_fetch_response_request_for_route( - command_session_id, - owner.session_owner_route(), - request_id, - pending, + conn.register_pending_subresource_fetch_response_request_for_owner( + owner, request_id, pending, ); return FetchCommandTaskStep::Complete(CommandOutputPlan::error( -32602, @@ -1681,11 +1620,8 @@ fn start_devtools_continue_intercepted_response_command( || response_headers.is_some() || command.response_phrase.is_some() { - conn.register_pending_subresource_fetch_response_request_for_route( - command_session_id, - owner.session_owner_route(), - request_id, - pending, + conn.register_pending_subresource_fetch_response_request_for_owner( + owner, request_id, pending, ); return FetchCommandTaskStep::Complete(CommandOutputPlan::error( -32602, @@ -1705,10 +1641,7 @@ fn start_devtools_continue_intercepted_response_command( response_headers }; let pending_internal_id = pending.internal_id; - let page = match conn.loaded_page_mut_for_protocol_access_for_route( - command_session_id, - owner.session_owner_route(), - ) { + let page = match conn.loaded_page_mut_for_protocol_access_for_owner(owner) { Ok(page) => page, Err(message) if message == "NoDocumentLoaded" => { return FetchCommandTaskStep::Complete(CommandOutputPlan::error( @@ -1812,12 +1745,7 @@ async fn continue_response_transfer_inline( .await; } Err(transfer) => { - conn.register_pending_fetch_response_transfer_for_route( - owner.session_id(), - owner.session_owner_route(), - request_id, - transfer, - ); + conn.register_pending_fetch_response_transfer_for_owner(owner, request_id, transfer); out.push_error(-32000, "ResponseBodyStreamActive"); } } @@ -1861,10 +1789,7 @@ pub(super) async fn complete_continue_response_command_async( return; } }; - match conn.loaded_page_mut_for_protocol_access_for_route( - owner.session_id(), - owner.session_owner_route(), - ) { + match conn.loaded_page_mut_for_protocol_access_for_owner(owner) { Ok(page) => { if let Err(error) = page.finish_continue_pending_subresource_response(completion) @@ -2364,9 +2289,8 @@ mod protocol_neutral_tests { ); assert!( - conn.take_pending_subresource_fetch_response_request_for_route( - Some("SID-primary"), - None, + conn.take_pending_subresource_fetch_response_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-primary"), Some("SID-primary"), "FETCH-response-aux", ) @@ -2374,9 +2298,8 @@ mod protocol_neutral_tests { "old owner action session must not be able to resolve the chained response" ); let chained = conn - .take_pending_subresource_fetch_response_request_for_route( - Some("SID-aux"), - None, + .take_pending_subresource_fetch_response_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-aux"), Some("SID-aux"), "FETCH-response-aux", ) @@ -2480,9 +2403,8 @@ mod protocol_neutral_tests { "BiDi-only session id has no CDP route and must not own the stored pending request" ); let chained = conn - .take_pending_subresource_fetch_request_for_route( - Some("SID-primary"), - None, + .take_pending_subresource_fetch_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-primary"), Some("BIDI-SID"), "FETCH-bidi", ) diff --git a/moli-protocol/src/domains/fetch/navigation.rs b/moli-protocol/src/domains/fetch/navigation.rs index f1fc6e47f4..ea45988928 100644 --- a/moli-protocol/src/domains/fetch/navigation.rs +++ b/moli-protocol/src/domains/fetch/navigation.rs @@ -37,10 +37,7 @@ fn prepare_navigation_response_stage( return true; } let Some(response_stage) = conn - .target_fetch_subresource_interception_snapshot_for_route( - pending.navigation.owner.session_id(), - pending.navigation.owner.session_owner_route(), - ) + .target_fetch_subresource_interception_snapshot_for_owner(&pending.navigation.owner) .and_then(|snapshot| { snapshot .matching_response_stage_pause_sessions( @@ -66,11 +63,9 @@ pub(crate) async fn load_or_pause_navigation_for_auth_into_buffer_async( prior_network_observation_journal: Option, ) { let navigate_owner = pending.navigation.owner.clone(); - let navigate_session_id = pending.navigation.owner.session_id().map(str::to_owned); network::record_main_document_request_body(conn, &pending.navigation); - let should_handle_auth = conn.target_fetch_matches_auth_required_for_route( - navigate_session_id.as_deref(), - navigate_owner.session_owner_route(), + let should_handle_auth = conn.target_fetch_matches_auth_required_for_owner( + &navigate_owner, &pending.navigation.requested_url, ) && pending.navigation.requested_url.scheme() != "data"; @@ -82,9 +77,8 @@ pub(crate) async fn load_or_pause_navigation_for_auth_into_buffer_async( let has_auth_credentials = auth.is_some(); if pending.intercept_response && navigation_response_stage_auth_can_stream(auth.as_ref()) { match conn - .fetch_navigation_streaming_raw_response_for_route_async( - navigate_session_id.as_deref(), - navigate_owner.session_owner_route(), + .fetch_navigation_streaming_raw_response_for_owner_async( + &navigate_owner, pending.navigation.request_load_policy, &method, &raw_url, @@ -140,9 +134,8 @@ pub(crate) async fn load_or_pause_navigation_for_auth_into_buffer_async( // before libcurl has completed the credential retry, so keep // credential replay on the buffered path until the fetch runtime // can mark intermediate auth responses separately. - conn.fetch_navigation_auth_raw_response_for_route_async( - navigate_session_id.as_deref(), - navigate_owner.session_owner_route(), + conn.fetch_navigation_auth_raw_response_for_owner_async( + &navigate_owner, pending.navigation.request_load_policy, &method, &raw_url, @@ -153,9 +146,8 @@ pub(crate) async fn load_or_pause_navigation_for_auth_into_buffer_async( .await } else { match conn - .fetch_navigation_streaming_raw_response_for_route_async( - navigate_session_id.as_deref(), - navigate_owner.session_owner_route(), + .fetch_navigation_streaming_raw_response_for_owner_async( + &navigate_owner, pending.navigation.request_load_policy, &method, &raw_url, @@ -225,9 +217,8 @@ pub(crate) async fn load_or_pause_navigation_for_auth_into_buffer_async( if pending.intercept_response && pending.navigation.requested_url.scheme() != "data" { match conn - .fetch_navigation_streaming_raw_response_for_route_async( - navigate_session_id.as_deref(), - navigate_owner.session_owner_route(), + .fetch_navigation_streaming_raw_response_for_owner_async( + &navigate_owner, pending.navigation.request_load_policy, &pending.navigation.request_method, pending.navigation.requested_url.as_str(), @@ -581,8 +572,8 @@ async fn handle_streaming_response_head_for_navigation_into_buffer_async( } }; let (response, network_observation_journal) = response.into_parts_with_observation_journal(); - conn.register_pending_fetch_response_navigation_for_session_owner( - pending.navigation.owner.session_id(), + conn.register_pending_fetch_response_navigation_for_owner( + &pending.navigation.owner, pending.fetch_request_id.clone(), pending.document_navigation_token.clone(), pending.navigation.clone(), @@ -690,8 +681,8 @@ fn pause_buffered_raw_response_stage_navigation_into_buffer( let response_headers = response.response().headers.clone(); let request_cookie_report = response.response().request_cookie_report.clone(); let (response, network_observation_journal) = response.into_parts_with_observation_journal(); - conn.register_pending_fetch_response_navigation_for_session_owner( - pending.navigation.owner.session_id(), + conn.register_pending_fetch_response_navigation_for_owner( + &pending.navigation.owner, pending.fetch_request_id.clone(), pending.document_navigation_token.clone(), pending.navigation.clone(), @@ -759,8 +750,6 @@ pub(crate) async fn continue_subresource_without_fetch_pause_async( handle_auth_requests: bool, owner_kind: PendingSubresourceFetchOwnerKind, ) { - let session_id = owner.session_id(); - let owner_route = owner.session_owner_route(); let pending = PendingSubresourceFetchRequest { residence: crate::conn::PendingSubresourceFetchResidence::InstalledPage(page_owner), owner_session_id: None, @@ -776,9 +765,8 @@ pub(crate) async fn continue_subresource_without_fetch_pause_async( request_stage_chain: None, }; if conn - .continue_pending_subresource_fetch_for_route_async( - session_id, - owner_route, + .continue_pending_subresource_fetch_for_owner_async( + owner, internal_id, None, None, @@ -790,12 +778,7 @@ pub(crate) async fn continue_subresource_without_fetch_pause_async( .await .is_ok() { - conn.register_in_flight_subresource_fetch_request_for_route( - session_id, - owner_route, - request_id, - pending, - ); + conn.register_in_flight_subresource_fetch_request_for_owner(owner, request_id, pending); } } @@ -806,8 +789,8 @@ fn navigation_auth_required_blocked_intercepts( if !pending.auth_required_blocked_intercepts.is_empty() { return pending.auth_required_blocked_intercepts.clone(); } - let intercepts = conn.target_fetch_matching_auth_required_network_intercepts_for_session_owner( - pending.navigation.owner.session_id(), + let intercepts = conn.target_fetch_matching_auth_required_network_intercepts_for_owner( + &pending.navigation.owner, &pending.navigation.requested_url, ); if !intercepts.is_empty() { @@ -875,10 +858,7 @@ fn register_navigation_auth_required_event( let auth_sessions = conn .target_fetch_subresource_interception_snapshot_for_target(&pending.navigation.frame_id) .or_else(|| { - conn.target_fetch_subresource_interception_snapshot_for_route( - pending.navigation.owner.session_id(), - pending.navigation.owner.session_owner_route(), - ) + conn.target_fetch_subresource_interception_snapshot_for_owner(&pending.navigation.owner) }) .map(|snapshot| { snapshot.matching_auth_required_pause_sessions( @@ -902,10 +882,9 @@ fn register_navigation_auth_required_event( ); let mut remaining_sessions = Vec::new(); for session in auth_sessions.into_iter().skip(1) { - let Ok(next_request_id) = conn.allocate_fetch_navigation_request_id_for_route( - pending.navigation.owner.session_id(), - pending.navigation.owner.session_owner_route(), - ) else { + let Ok(next_request_id) = + conn.allocate_fetch_navigation_request_id_for_owner(&pending.navigation.owner) + else { break; }; remaining_sessions.push(PendingSubresourceFetchAuthStage { @@ -930,13 +909,11 @@ fn register_navigation_auth_required_event( .owner_session_id .as_deref() .or(pending.navigation.owner.session_id()); - let pending_owner_route = pending_owner_session_id - .is_none() - .then(|| pending.navigation.owner.session_owner_route()) - .flatten(); - conn.register_pending_fetch_auth_navigation_for_route( - pending_owner_session_id, - pending_owner_route, + let pending_owner = pending_owner_session_id + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| pending.navigation.owner.clone()); + conn.register_pending_fetch_auth_navigation_for_owner( + &pending_owner, pending.fetch_request_id.clone(), pending_auth.clone(), ); @@ -956,14 +933,12 @@ pub(crate) async fn continue_subresource_for_response_stage_async( handle_auth_requests: bool, response_stage_blocked_intercepts: Vec, ) { - let owner_route = session_id - .is_none() - .then(|| owner.session_owner_route()) - .flatten(); + let action_owner = session_id + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); if conn - .continue_pending_subresource_fetch_for_route_async( - session_id, - owner_route, + .continue_pending_subresource_fetch_for_owner_async( + &action_owner, pending.internal_id, None, None, @@ -975,9 +950,8 @@ pub(crate) async fn continue_subresource_for_response_stage_async( .await .is_ok() { - conn.register_in_flight_response_stage_subresource_fetch_request_for_route( - session_id, - owner_route, + conn.register_in_flight_response_stage_subresource_fetch_request_for_owner( + &action_owner, Some(request_id), pending, response_stage_blocked_intercepts, @@ -993,14 +967,12 @@ pub(crate) async fn continue_subresource_for_deferred_response_stage_async( pending: PendingSubresourceFetchRequest, handle_auth_requests: bool, ) { - let owner_route = session_id - .is_none() - .then(|| owner.session_owner_route()) - .flatten(); + let action_owner = session_id + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); if conn - .continue_pending_subresource_fetch_for_route_async( - session_id, - owner_route, + .continue_pending_subresource_fetch_for_owner_async( + &action_owner, pending.internal_id, None, None, @@ -1012,9 +984,8 @@ pub(crate) async fn continue_subresource_for_deferred_response_stage_async( .await .is_ok() { - conn.register_in_flight_deferred_response_stage_subresource_fetch_request_for_route( - session_id, - owner_route, + conn.register_in_flight_deferred_response_stage_subresource_fetch_request_for_owner( + &action_owner, Some(request_id), pending, ); diff --git a/moli-protocol/src/domains/fetch/state.rs b/moli-protocol/src/domains/fetch/state.rs index 14ed512c98..e996f0ccf8 100644 --- a/moli-protocol/src/domains/fetch/state.rs +++ b/moli-protocol/src/domains/fetch/state.rs @@ -27,9 +27,8 @@ impl PreparedSubresourceCorrelation { should_register: bool, ) -> Option { if should_register - && !conn.register_in_flight_subresource_fetch_request_for_route( - owner.session_id(), - owner.session_owner_route(), + && !conn.register_in_flight_subresource_fetch_request_for_owner( + owner, Some(request_id.to_owned()), pending.clone(), ) @@ -45,9 +44,8 @@ impl PreparedSubresourceCorrelation { pub(super) fn rollback(self, conn: &mut CdpConnection) { if self.registered { - conn.take_in_flight_subresource_fetch_request_for_route( - self.owner_scope.session_id(), - self.owner_scope.session_owner_route(), + conn.take_in_flight_subresource_fetch_request_for_owner( + &self.owner_scope, self.internal_id, ); } @@ -59,9 +57,8 @@ impl PreparedSubresourceCorrelation { request_id: &str, pending: &PendingSubresourceFetchRequest, ) -> Option { - if !conn.register_in_flight_deferred_response_stage_subresource_fetch_request_for_route( - owner.session_id(), - owner.session_owner_route(), + if !conn.register_in_flight_deferred_response_stage_subresource_fetch_request_for_owner( + owner, Some(request_id.to_owned()), pending.clone(), ) { @@ -123,11 +120,7 @@ pub(crate) fn pending_request_action_result_with_id_validation( if validate_id && validate_request_id(request_id).is_err() { return Err(CommandOutputPlan::error(-32602, "InvalidParams")); } - let Some(result) = conn.consume_pending_request_action_for_route( - owner.session_id(), - owner.session_owner_route(), - request_id, - ) else { + let Some(result) = conn.consume_pending_request_action_for_owner(owner, request_id) else { return Err(CommandOutputPlan::error(-31998, "BrowserContextNotLoaded")); }; if result.is_err() { @@ -142,12 +135,7 @@ pub(crate) fn take_pending_navigation( action_session_id: Option<&str>, request_id: &str, ) -> Option { - conn.take_pending_fetch_navigation_for_route( - owner.session_id(), - owner.session_owner_route(), - action_session_id, - request_id, - ) + conn.take_pending_fetch_navigation_for_owner(owner, action_session_id, request_id) } pub(crate) fn take_pending_auth_navigation_for_action_session( @@ -156,12 +144,7 @@ pub(crate) fn take_pending_auth_navigation_for_action_session( action_session_id: Option<&str>, request_id: &str, ) -> Option { - conn.take_pending_fetch_auth_navigation_for_route( - owner.session_id(), - owner.session_owner_route(), - action_session_id, - request_id, - ) + conn.take_pending_fetch_auth_navigation_for_owner(owner, action_session_id, request_id) } pub(crate) fn take_pending_subresource_fetch_request_for_action_session( @@ -170,12 +153,7 @@ pub(crate) fn take_pending_subresource_fetch_request_for_action_session( action_session_id: Option<&str>, request_id: &str, ) -> Option { - conn.take_pending_subresource_fetch_request_for_route( - owner.session_id(), - owner.session_owner_route(), - action_session_id, - request_id, - ) + conn.take_pending_subresource_fetch_request_for_owner(owner, action_session_id, request_id) } pub(crate) fn take_pending_subresource_auth_request_for_action_session( @@ -184,12 +162,7 @@ pub(crate) fn take_pending_subresource_auth_request_for_action_session( action_session_id: Option<&str>, request_id: &str, ) -> Option { - conn.take_pending_subresource_fetch_auth_request_for_route( - owner.session_id(), - owner.session_owner_route(), - action_session_id, - request_id, - ) + conn.take_pending_subresource_fetch_auth_request_for_owner(owner, action_session_id, request_id) } pub(crate) fn take_pending_subresource_response_request_for_action_session( @@ -198,9 +171,8 @@ pub(crate) fn take_pending_subresource_response_request_for_action_session( action_session_id: Option<&str>, request_id: &str, ) -> Option { - conn.take_pending_subresource_fetch_response_request_for_route( - owner.session_id(), - owner.session_owner_route(), + conn.take_pending_subresource_fetch_response_request_for_owner( + owner, action_session_id, request_id, ) @@ -212,12 +184,7 @@ pub(crate) fn pending_subresource_response_request_for_action_session( action_session_id: Option<&str>, request_id: &str, ) -> Option { - conn.pending_subresource_fetch_response_request_for_route( - owner.session_id(), - owner.session_owner_route(), - action_session_id, - request_id, - ) + conn.pending_subresource_fetch_response_request_for_owner(owner, action_session_id, request_id) } pub(crate) fn mark_pending_subresource_response_body_taken_as_stream_for_action_session( @@ -226,9 +193,8 @@ pub(crate) fn mark_pending_subresource_response_body_taken_as_stream_for_action_ action_session_id: Option<&str>, request_id: &str, ) -> bool { - conn.mark_pending_subresource_fetch_response_body_taken_as_stream_for_route( - owner.session_id(), - owner.session_owner_route(), + conn.mark_pending_subresource_fetch_response_body_taken_as_stream_for_owner( + owner, action_session_id, request_id, ) diff --git a/moli-protocol/src/domains/fetch/subresource.rs b/moli-protocol/src/domains/fetch/subresource.rs index 149c06eeec..242b4b0ef8 100644 --- a/moli-protocol/src/domains/fetch/subresource.rs +++ b/moli-protocol/src/domains/fetch/subresource.rs @@ -61,11 +61,7 @@ pub(crate) async fn subresource_fetch_pause_prepared_outputs_for_renderer_record source_document: moli_core::RendererDocumentLifecycleIdentity, info: moli_core::page::PendingSubresourceFetchInfo, ) -> network::NetworkPreparedOutputs { - if conn.target_root_document_lifecycle_identity_for_route( - owner.session_id(), - owner.session_owner_route(), - ) != Some(source_document) - { + if conn.target_root_document_lifecycle_identity_for_owner(owner) != Some(source_document) { return network::NetworkPreparedOutputs::default(); } network::NetworkPreparedOutputs::from_subresource_fetch_pauses( @@ -90,11 +86,7 @@ pub(crate) async fn detached_parser_script_fetch_pause_prepared_outputs_for_rend info: moli_core::page::PendingSubresourceFetchInfo, continuation: DetachedParserScriptFetchContinuation, ) -> network::NetworkPreparedOutputs { - if conn.target_root_document_lifecycle_identity_for_route( - owner.session_id(), - owner.session_owner_route(), - ) != Some(source_document) - { + if conn.target_root_document_lifecycle_identity_for_owner(owner) != Some(source_document) { return network::NetworkPreparedOutputs::default(); } network::NetworkPreparedOutputs::from_subresource_fetch_pauses( @@ -121,22 +113,21 @@ async fn prepare_subresource_fetch_pause_sources_async( ) -> Vec { let mut outputs = Vec::new(); let session_id = owner.session_id(); - let owner_route = owner.session_owner_route(); - let page_owner = conn.target_page_residence_identity_for_route(session_id, owner_route); + let page_owner = conn.target_page_residence_identity_for_owner(owner); let Some((fetch_snapshot, frame_id)) = (|| { let target_frame_id = conn - .target_session_owner_frame_tree_identity_for_route(session_id, owner_route) + .target_session_owner_frame_tree_identity_for_owner(owner) .map(|(target_id, _, _, _)| target_id)?; let frame_id = frame_id.unwrap_or(&target_frame_id); Some(( - conn.target_fetch_subresource_interception_snapshot_for_route(session_id, owner_route)?, + conn.target_fetch_subresource_interception_snapshot_for_owner(owner)?, frame_id.to_owned(), )) })() else { return outputs; }; let loader_id = conn - .current_document_loader_id_for_route(session_id, owner_route) + .current_document_loader_id_for_owner(owner) .unwrap_or_else(|| DEFAULT_LOADER_ID.to_owned()); for source in sources { let PendingSubresourceFetchPauseSource { @@ -144,7 +135,7 @@ async fn prepare_subresource_fetch_pause_sources_async( detached_parser_script_fetch_continuation, } = source; let Ok((request_id, network_request_id)) = - conn.allocate_pending_subresource_fetch_request_ids_for_route(session_id, owner_route) + conn.allocate_pending_subresource_fetch_request_ids_for_owner(owner) else { return outputs; }; @@ -307,8 +298,8 @@ async fn prepare_subresource_fetch_pause_sources_async( ); let mut remaining_sessions = Vec::new(); for session in request_stage_pause_sessions.into_iter().skip(1) { - let Ok((next_request_id, _)) = conn - .allocate_pending_subresource_fetch_request_ids_for_route(session_id, owner_route) + let Ok((next_request_id, _)) = + conn.allocate_pending_subresource_fetch_request_ids_for_owner(owner) else { return outputs; }; @@ -385,10 +376,9 @@ pub(crate) fn emit_subresource_fetch_pause_outputs( .as_deref() .filter(|session_id| conn.session_route(Some(session_id)).is_some()) .or(owner.session_id()); - let pending_owner_route = pending_owner_session_id - .is_none() - .then(|| owner.session_owner_route()) - .flatten(); + let pending_owner = pending_owner_session_id + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); pending.action_session_id = event_session_id.clone(); let blocked_intercepts = blocked_intercepts_from_fetch_payload(&payload); let fetch_event = subresource_request_paused_event( @@ -398,17 +388,14 @@ pub(crate) fn emit_subresource_fetch_pause_outputs( payload, blocked_intercepts, ); - if !conn.register_pending_subresource_fetch_request_for_route( - pending_owner_session_id, - pending_owner_route, + if !conn.register_pending_subresource_fetch_request_for_owner( + &pending_owner, request_id, pending, ) { return; } - if let Ok(runtime_slot) = conn - .runtime_session_owner_slot_mut_for_route(pending_owner_session_id, pending_owner_route) - { + if let Ok(runtime_slot) = conn.runtime_session_owner_slot_mut_for_owner(&pending_owner) { // Chromium publishes Network.requestWillBeSent before the Fetch pause. // The renderer's later transport start belongs to the same lifecycle // and must not publish a second initial Network event. diff --git a/moli-protocol/src/domains/fetch/tests/command_correlation.rs b/moli-protocol/src/domains/fetch/tests/command_correlation.rs index 0ac3cc2d30..1db1363bf9 100644 --- a/moli-protocol/src/domains/fetch/tests/command_correlation.rs +++ b/moli-protocol/src/domains/fetch/tests/command_correlation.rs @@ -130,7 +130,10 @@ async fn assert_correlation_lifetime( assert!(matches!(&step, CdpCommandTaskStep::Pending(_))); assert_eq!( ctx.conn - .in_flight_subresource_fetch_request_id_for_route(Some("SID-1"), None, internal_id,) + .in_flight_subresource_fetch_request_id_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), + internal_id, + ) .as_deref(), Some(request_id), "renderer-visible network work must have protocol correlation state" @@ -144,8 +147,10 @@ async fn assert_correlation_lifetime( "the synthetic unknown renderer request should fail" ); assert_eq!( - ctx.conn - .in_flight_subresource_fetch_request_id_for_route(Some("SID-1"), None, internal_id,), + ctx.conn.in_flight_subresource_fetch_request_id_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), + internal_id, + ), None, "failed renderer completion must roll back prepared correlation state" ); @@ -174,10 +179,8 @@ async fn deferred_fetch_command_keeps_its_exact_page_for_implicit_work() { .wait() .await; assert_eq!( - ctx.conn.target_owner_identity_for_route( - completed.owner_scope.session_id(), - completed.owner_scope.session_owner_route(), - ), + ctx.conn + .target_owner_identity_for_owner(&completed.owner_scope,), Some(("BID-1".to_owned(), Some("TID-background".to_owned()))), "protocol-neutral completion work must stay on the Page that issued the Fetch command" ); @@ -210,10 +213,8 @@ async fn deferred_sessionless_fetch_command_freezes_the_active_page_at_admission .expect("browser context") .set_active_target_id("TID-next"); assert_eq!( - ctx.conn.target_owner_identity_for_route( - completed.owner_scope.session_id(), - completed.owner_scope.session_owner_route(), - ), + ctx.conn + .target_owner_identity_for_owner(&completed.owner_scope,), Some(( "BID-sessionless".to_owned(), Some("TID-original".to_owned()) @@ -275,9 +276,8 @@ async fn pending_fetch_command_state_is_bound_to_page_attachment() { .replace_page_attachment_id_for_test(); assert!( ctx.conn - .take_pending_subresource_fetch_request_for_route( - Some("SID-1"), - None, + .take_pending_subresource_fetch_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), Some("SID-1"), "INT-collision", ) @@ -301,9 +301,8 @@ async fn pending_fetch_command_state_is_bound_to_page_attachment() { ); assert_eq!( ctx.conn - .take_pending_subresource_fetch_request_for_route( - Some("SID-1"), - None, + .take_pending_subresource_fetch_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), Some("SID-1"), "INT-collision", ) @@ -331,9 +330,8 @@ async fn completed_continue_atomically_claims_a_pause_still_pending_publication( assert!( ctx.conn - .claim_subresource_continue_request_for_route( - Some("SID-1"), - None, + .claim_subresource_continue_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), &page_owner, 74, false, @@ -343,7 +341,12 @@ async fn completed_continue_atomically_claims_a_pause_still_pending_publication( ); let claimed = ctx .conn - .claim_subresource_continue_request_for_route(Some("SID-1"), None, &page_owner, 74, true) + .claim_subresource_continue_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), + &page_owner, + 74, + true, + ) .expect("terminal completion should claim the still-pending pause"); let ClaimedSubresourceContinueRequest::PendingCompletion(pending) = claimed else { panic!("terminal completion must preserve the pending-publication race state"); @@ -351,9 +354,8 @@ async fn completed_continue_atomically_claims_a_pause_still_pending_publication( assert_eq!(pending.network_request_id, "NETWORK-74"); assert!( ctx.conn - .claim_subresource_continue_request_for_route( - Some("SID-1"), - None, + .claim_subresource_continue_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), &page_owner, 74, true, @@ -373,18 +375,16 @@ async fn completed_continue_atomically_claims_a_pause_still_pending_publication( let replacement = pending_request(&replacement_owner, 75); assert!( ctx.conn - .register_in_flight_subresource_fetch_request_for_route( - Some("SID-1"), - None, + .register_in_flight_subresource_fetch_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), Some("INT-replacement".to_owned()), replacement, ) ); assert!( ctx.conn - .claim_subresource_continue_request_for_route( - Some("SID-1"), - None, + .claim_subresource_continue_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), &page_owner, 75, true, @@ -394,7 +394,10 @@ async fn completed_continue_atomically_claims_a_pause_still_pending_publication( ); assert_eq!( ctx.conn - .in_flight_subresource_fetch_request_id_for_route(Some("SID-1"), None, 75) + .in_flight_subresource_fetch_request_id_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), + 75 + ) .as_deref(), Some("INT-replacement"), "a rejected stale capture must leave the replacement request resident" @@ -410,9 +413,8 @@ async fn continuation_claim_preserves_state_owned_by_a_different_page_residence( .expect("initial Page residence should exist"); assert!( ctx.conn - .register_in_flight_subresource_fetch_request_for_route( - Some("SID-1"), - None, + .register_in_flight_subresource_fetch_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), Some("INT-retired-in-flight".to_owned()), pending_request(&retired_owner, 76), ) @@ -437,9 +439,8 @@ async fn continuation_claim_preserves_state_owned_by_a_different_page_residence( assert!( ctx.conn - .claim_subresource_continue_request_for_route( - Some("SID-1"), - None, + .claim_subresource_continue_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), &replacement_owner, 76, false, @@ -449,9 +450,8 @@ async fn continuation_claim_preserves_state_owned_by_a_different_page_residence( ); assert!( ctx.conn - .claim_subresource_continue_request_for_route( - Some("SID-1"), - None, + .claim_subresource_continue_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), &replacement_owner, 77, true, @@ -466,9 +466,8 @@ async fn continuation_claim_preserves_state_owned_by_a_different_page_residence( .install_page_attachment_id_for_test(retired_owner.page_attachment_id()); let ClaimedSubresourceContinueRequest::InFlight(in_flight) = ctx .conn - .claim_subresource_continue_request_for_route( - Some("SID-1"), - None, + .claim_subresource_continue_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), &retired_owner, 76, false, @@ -484,7 +483,12 @@ async fn continuation_claim_preserves_state_owned_by_a_different_page_residence( let ClaimedSubresourceContinueRequest::PendingCompletion(pending) = ctx .conn - .claim_subresource_continue_request_for_route(Some("SID-1"), None, &retired_owner, 77, true) + .claim_subresource_continue_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), + &retired_owner, + 77, + true, + ) .expect("owner mismatch must leave the pending request resident") else { panic!("the preserved request should remain pending"); @@ -514,9 +518,8 @@ async fn pending_fetch_auth_state_is_bound_to_page_attachment() { .replace_page_attachment_id_for_test(); assert!( ctx.conn - .take_pending_subresource_fetch_auth_request_for_route( - Some("SID-1"), - None, + .take_pending_subresource_fetch_auth_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), Some("SID-1"), "AUTH-collision", ) @@ -540,9 +543,8 @@ async fn pending_fetch_auth_state_is_bound_to_page_attachment() { ); assert_eq!( ctx.conn - .take_pending_subresource_fetch_auth_request_for_route( - Some("SID-1"), - None, + .take_pending_subresource_fetch_auth_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), Some("SID-1"), "AUTH-collision", ) @@ -574,9 +576,8 @@ async fn pending_fetch_response_state_is_bound_to_page_attachment() { .replace_page_attachment_id_for_test(); assert!( ctx.conn - .take_pending_subresource_fetch_response_request_for_route( - Some("SID-1"), - None, + .take_pending_subresource_fetch_response_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), Some("SID-1"), "RESPONSE-collision", ) @@ -600,9 +601,8 @@ async fn pending_fetch_response_state_is_bound_to_page_attachment() { ); assert_eq!( ctx.conn - .take_pending_subresource_fetch_response_request_for_route( - Some("SID-1"), - None, + .take_pending_subresource_fetch_response_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), Some("SID-1"), "RESPONSE-collision", ) diff --git a/moli-protocol/src/domains/fetch/tests/navigation_auth.rs b/moli-protocol/src/domains/fetch/tests/navigation_auth.rs index 25b31ae09a..c0966649fe 100644 --- a/moli-protocol/src/domains/fetch/tests/navigation_auth.rs +++ b/moli-protocol/src/domains/fetch/tests/navigation_auth.rs @@ -927,7 +927,9 @@ async fn run_navigation_cdp_fetch_then_bidi_network_auth_required_terminal( let parsed_url = Url::parse(&url).unwrap(); let auth_pause_sessions = ctx .conn - .target_fetch_subresource_interception_snapshot_for_route(Some("SID-1"), None) + .target_fetch_subresource_interception_snapshot_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), + ) .expect("active target fetch snapshot") .matching_auth_required_pause_sessions(Some("SID-1"), &parsed_url); assert_eq!( diff --git a/moli-protocol/src/domains/fetch/tests/runtime_auth_response.rs b/moli-protocol/src/domains/fetch/tests/runtime_auth_response.rs index cc0c769cd6..73a8acf3b0 100644 --- a/moli-protocol/src/domains/fetch/tests/runtime_auth_response.rs +++ b/moli-protocol/src/domains/fetch/tests/runtime_auth_response.rs @@ -1825,7 +1825,9 @@ async fn run_cdp_fetch_then_bidi_network_auth_required_terminal_credentials_comp let protected_parsed_url = Url::parse(&protected_url).unwrap(); let auth_pause_sessions = ctx .conn - .target_fetch_subresource_interception_snapshot_for_route(Some("SID-1"), None) + .target_fetch_subresource_interception_snapshot_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), + ) .expect("active target fetch snapshot") .matching_auth_required_pause_sessions(Some("SID-1"), &protected_parsed_url); assert_eq!( diff --git a/moli-protocol/src/domains/fetch/tests/runtime_fetch.rs b/moli-protocol/src/domains/fetch/tests/runtime_fetch.rs index 366a789cee..e6378da0a5 100644 --- a/moli-protocol/src/domains/fetch/tests/runtime_fetch.rs +++ b/moli-protocol/src/domains/fetch/tests/runtime_fetch.rs @@ -1139,7 +1139,9 @@ async fn response_body_stream_taken_blocks_chained_bidi_response_stage_pause() { let api_url = Url::parse(&hit_url).unwrap(); let response_pause_sessions = ctx .conn - .target_fetch_subresource_interception_snapshot_for_route(Some("SID-1"), None) + .target_fetch_subresource_interception_snapshot_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), + ) .expect("active target fetch snapshot") .matching_response_stage_pause_sessions( Some("SID-1"), @@ -6992,7 +6994,9 @@ async fn cdp_fetch_then_bidi_network_intercept_response_stage_chain_completes() let api_url = Url::parse(&hit_url).unwrap(); let response_pause_sessions = ctx .conn - .target_fetch_subresource_interception_snapshot_for_route(Some("SID-1"), None) + .target_fetch_subresource_interception_snapshot_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), + ) .expect("active target fetch snapshot") .matching_response_stage_pause_sessions( Some("SID-1"), diff --git a/moli-protocol/src/domains/input.rs b/moli-protocol/src/domains/input.rs index 69cd0c6a92..b3760da052 100644 --- a/moli-protocol/src/domains/input.rs +++ b/moli-protocol/src/domains/input.rs @@ -343,7 +343,7 @@ fn set_ignore_input_events_command_output_plan( } fn input_events_ignored_for_owner(conn: &CdpConnection, owner: &CommandOwnerScope) -> bool { - conn.page_event_session_ids_for_route(owner.session_id(), owner.session_owner_route()) + conn.page_event_session_ids_for_owner(owner) .into_iter() .any(|event_session_id| { conn.target_page_session_state_for_session(event_session_id.as_deref()) @@ -572,8 +572,7 @@ fn start_pending_input_command( ) -> Result, PendingInputCommandStartError> { let owner = CommandOwnerScope::capture(conn, cmd.session_id); if action.requires_document_access() - && let Err(message) = conn - .ensure_document_accessible_for_route(owner.session_id(), owner.session_owner_route()) + && let Err(message) = conn.ensure_document_accessible_for_owner(&owner) { return Err(PendingInputCommandStartError { code: -32000, @@ -1005,27 +1004,18 @@ fn start_page_input_command( start: impl FnOnce(&Page) -> anyhow::Result, ) -> Result, PendingInputCommandStartError> { let page_owner = conn - .target_page_residence_identity_for_route( - command_owner.session_id(), - command_owner.session_owner_route(), - ) + .target_page_residence_identity_for_owner(command_owner) .ok_or_else(PendingInputCommandStartError::no_document_loaded)?; let page_residence_token = if kind.uses_renderer_host_ack_cleanup() { Some( - conn.capture_target_page_residence_token_for_route( - command_owner.session_id(), - command_owner.session_owner_route(), - ) - .ok_or_else(PendingInputCommandStartError::no_document_loaded)?, + conn.capture_target_page_residence_token_for_owner(command_owner) + .ok_or_else(PendingInputCommandStartError::no_document_loaded)?, ) } else { None }; let page = conn - .loaded_page_mut_for_protocol_access_for_route( - command_owner.session_id(), - command_owner.session_owner_route(), - ) + .loaded_page_mut_for_protocol_access_for_owner(command_owner) .ok() .ok_or_else(PendingInputCommandStartError::no_document_loaded)?; let pending = start(page).map_err(PendingInputCommandStartError::renderer_error)?; @@ -1519,10 +1509,7 @@ impl InputPreparedOutputs { owner: &CommandOwnerScope, activation: RendererPendingFileChooserActivation, ) -> Self { - let Some(page_owner) = conn.target_page_residence_identity_for_route( - owner.session_id(), - owner.session_owner_route(), - ) else { + let Some(page_owner) = conn.target_page_residence_identity_for_owner(owner) else { return Self::default(); }; let Some(activation) = file_chooser::PreparedFileChooserActivation::capture( @@ -1630,7 +1617,7 @@ async fn handle_input_dispatch_outcome_async( let mut events = Vec::new(); conn.handle_pending_download_activation_background_events_async( &mut events, - session_id, + &action_owner, download, command_context, ) @@ -1648,7 +1635,7 @@ async fn handle_input_dispatch_outcome_async( file_chooser::emit_prepared_activation_async( conn, out.events_mut(), - session_id, + &action_owner, file_chooser, ) .await; @@ -1663,7 +1650,7 @@ async fn handle_input_dispatch_outcome_async( pub(in crate::domains) async fn emit_download_activity_background_events_async( conn: &mut CdpConnection, out: &mut Vec, - session_id: Option<&str>, + owner: &CommandOwnerScope, prepared_outputs: Option<&mut ProtocolOutputPayloads>, command_context: &mut CommandDispatchContext, ) { @@ -1671,14 +1658,14 @@ pub(in crate::domains) async fn emit_download_activity_background_events_async( .and_then(ProtocolOutputPayloads::input_mut) .and_then(InputPreparedOutputSlot::take_download_activations) { - emit_download_activations(conn, out, session_id, activations, command_context).await; + emit_download_activations(conn, out, owner, activations, command_context).await; } } async fn emit_download_activations( conn: &mut CdpConnection, out: &mut Vec, - session_id: Option<&str>, + owner: &CommandOwnerScope, activations: Vec, command_context: &mut CommandDispatchContext, ) { @@ -1686,7 +1673,7 @@ async fn emit_download_activations( if let Err(error) = conn .handle_pending_download_activation_background_events_async( out, - session_id, + owner, activation, command_context, ) @@ -1703,14 +1690,14 @@ async fn emit_download_activations( pub(in crate::domains) async fn emit_file_chooser_activity_background_events_async( conn: &mut CdpConnection, out: &mut Vec, - session_id: Option<&str>, + owner: &CommandOwnerScope, prepared_outputs: Option<&mut ProtocolOutputPayloads>, ) { if let Some(activations) = prepared_outputs .and_then(ProtocolOutputPayloads::input_mut) .and_then(InputPreparedOutputSlot::take_file_chooser_activations) { - file_chooser::emit_prepared_activations_async(conn, out, session_id, activations).await; + file_chooser::emit_prepared_activations_async(conn, out, owner, activations).await; } } @@ -2200,7 +2187,7 @@ mod producer_tests { super::file_chooser::emit_prepared_activation_async( &mut conn, &mut out, - Some("SID-typed"), + &CommandOwnerScope::for_session("SID-typed"), prepared, ) .await; @@ -2297,7 +2284,7 @@ mod producer_tests { super::file_chooser::emit_prepared_activation_async( &mut conn, &mut out, - Some("SID-document-collision"), + &CommandOwnerScope::for_session("SID-document-collision"), prepared, ) .await; @@ -2378,7 +2365,7 @@ mod producer_tests { super::file_chooser::emit_prepared_activations_async( &mut conn, &mut out, - Some("SID-page-replacement"), + &CommandOwnerScope::for_session("SID-page-replacement"), vec![stale, current], ) .await; @@ -2421,7 +2408,7 @@ mod producer_tests { super::emit_download_activity_background_events_async( &mut conn, &mut out, - Some("SID-download"), + &CommandOwnerScope::for_session("SID-download"), Some(&mut prepared), &mut command_context, ) @@ -2476,7 +2463,7 @@ mod producer_tests { super::emit_file_chooser_activity_background_events_async( &mut conn, &mut out, - Some("SID-1"), + &CommandOwnerScope::for_session("SID-1"), Some(&mut prepared), ) .await; @@ -2524,7 +2511,7 @@ mod producer_tests { super::emit_file_chooser_activity_background_events_async( &mut conn, &mut out, - Some("SID-context"), + &CommandOwnerScope::for_session("SID-context"), Some(&mut prepared), ) .await; diff --git a/moli-protocol/src/domains/input/file_chooser.rs b/moli-protocol/src/domains/input/file_chooser.rs index 863dfbb19b..ca27156999 100644 --- a/moli-protocol/src/domains/input/file_chooser.rs +++ b/moli-protocol/src/domains/input/file_chooser.rs @@ -35,9 +35,7 @@ impl PreparedFileChooserActivation { page_owner: TargetPageResidenceIdentity, activation: RendererPendingFileChooserActivation, ) -> Option { - if !conn - .target_page_residence_identity_is_current_for_session(owner.session_id(), &page_owner) - { + if !conn.target_page_residence_identity_is_current(&page_owner) { return None; } let source_document = activation.source_document(); @@ -45,11 +43,8 @@ impl PreparedFileChooserActivation { .source_frame_id() .map(str::to_owned) .or_else(|| { - conn.target_session_owner_frame_tree_identity_for_route( - owner.session_id(), - owner.session_owner_route(), - ) - .map(|(frame_id, _, _, _)| frame_id) + conn.target_session_owner_frame_tree_identity_for_owner(owner) + .map(|(frame_id, _, _, _)| frame_id) })?; Some(Self { page_owner, @@ -94,26 +89,27 @@ impl PreparedFileChooserActivation { pub(super) async fn emit_prepared_activations_async( conn: &mut CdpConnection, out: &mut Vec, - session_id: Option<&str>, + owner: &CommandOwnerScope, activations: Vec, ) { for activation in activations { - emit_prepared_activation_async(conn, out, session_id, activation).await; + emit_prepared_activation_async(conn, out, owner, activation).await; } } pub(super) async fn emit_prepared_activation_async( conn: &mut CdpConnection, out: &mut Vec, - session_id: Option<&str>, + owner: &CommandOwnerScope, activation: PreparedFileChooserActivation, ) { - if !activation_is_current(conn, session_id, &activation) { + let session_id = owner.session_id(); + if !activation_is_current(conn, &activation) { trace_stale_activation(session_id, &activation); return; } let event_enabled = conn - .target_page_session_state_for_session(session_id) + .target_page_session_state_for_owner(owner) .is_some_and(|state| { state.page_intercept_file_chooser_dialog_enabled || state.page_file_chooser_opened_event_enabled @@ -126,9 +122,8 @@ pub(super) async fn emit_prepared_activation_async( } else { "selectSingle" }; - let element_shared_id = - element_shared_id_async(conn, session_id, activation.backend_node_id).await; - if !activation_is_current(conn, session_id, &activation) { + let element_shared_id = element_shared_id_async(conn, owner, activation.backend_node_id).await; + if !activation_is_current(conn, &activation) { trace_stale_activation(session_id, &activation); return; } @@ -141,12 +136,8 @@ pub(super) async fn emit_prepared_activation_async( )); } -fn activation_is_current( - conn: &CdpConnection, - session_id: Option<&str>, - activation: &PreparedFileChooserActivation, -) -> bool { - conn.target_page_residence_identity_is_current_for_session(session_id, &activation.page_owner) +fn activation_is_current(conn: &CdpConnection, activation: &PreparedFileChooserActivation) -> bool { + conn.target_page_residence_identity_is_current(&activation.page_owner) } fn trace_stale_activation(session_id: Option<&str>, activation: &PreparedFileChooserActivation) { @@ -164,7 +155,7 @@ fn trace_stale_activation(session_id: Option<&str>, activation: &PreparedFileCho async fn element_shared_id_async( conn: &mut CdpConnection, - session_id: Option<&str>, + owner: &CommandOwnerScope, backend_node_id: u32, ) -> DevToolsRemoteHandleId { // The event identity belongs to the frozen activation, while the DOM-agent @@ -173,10 +164,7 @@ async fn element_shared_id_async( // before or during this async handoff; it must not erase the element from // the already-accepted file-chooser event. match conn - .document_bidi_node_shared_id_for_backend_node_id_for_session_owner_async( - session_id, - backend_node_id, - ) + .document_bidi_node_shared_id_for_backend_node_id_for_owner_async(owner, backend_node_id) .await { Ok(RendererDomBidiNodeSharedIdResolution::SharedId(shared_id)) => { @@ -194,8 +182,8 @@ async fn element_shared_id_async( let shared_id = webdriver_bidi_node_shared_id_for_backend_node_id(backend_node_id); if let Err(error) = conn - .register_document_bidi_node_binding_for_session_owner_async( - session_id, + .register_document_bidi_node_binding_for_owner_async( + owner, shared_id.as_str(), backend_node_id, ) diff --git a/moli-protocol/src/domains/input/tests.rs b/moli-protocol/src/domains/input/tests.rs index 8c542b0b81..281b6458ce 100644 --- a/moli-protocol/src/domains/input/tests.rs +++ b/moli-protocol/src/domains/input/tests.rs @@ -333,9 +333,10 @@ async fn pending_mouse_event_acknowledges_when_page_is_replaced_before_renderer_ .conn .target_page_residence_identity_for_session(None) .expect("the original Page should have a residence identity"); + let command_owner = CommandOwnerScope::capture(&ctx.conn, None); let page_residence_token = ctx .conn - .capture_target_page_residence_token_for_route(None, None) + .capture_target_page_residence_token_for_owner(&command_owner) .expect("the original Page should expose its attachment lifetime"); let replacement_url = "data:text/html,replacement-before-completion"; @@ -375,9 +376,10 @@ async fn completed_renderer_ack_wins_when_page_replacement_is_already_observable let mut ctx = TestContext::new(); with_loaded_document(&mut ctx, "origin").await; + let command_owner = CommandOwnerScope::capture(&ctx.conn, None); let page_residence_token = ctx .conn - .capture_target_page_residence_token_for_route(None, None) + .capture_target_page_residence_token_for_owner(&command_owner) .expect("the original Page should expose its attachment lifetime"); ctx.install_navigation_fixture_for_session_owner( "data:text/html,replacement-after-ack", diff --git a/moli-protocol/src/domains/network.rs b/moli-protocol/src/domains/network.rs index c13c2656c8..abf3348eb0 100644 --- a/moli-protocol/src/domains/network.rs +++ b/moli-protocol/src/domains/network.rs @@ -738,11 +738,8 @@ fn complete_network_policy_refresh( } }; if let Err(error) = finish_network_page_operation_on_current_attachment( - conn.loaded_page_mut_for_target_configuration_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) - .ok(), + conn.loaded_page_mut_for_target_configuration_for_owner(&owner_scope) + .ok(), NetworkPageCommandFinish::RequestPolicy, completion, ) { @@ -780,11 +777,8 @@ fn complete_unit_page_network_command( } }; match finish_network_page_operation_on_current_attachment( - conn.loaded_page_mut_for_target_configuration_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) - .ok(), + conn.loaded_page_mut_for_target_configuration_for_owner(&owner_scope) + .ok(), finish, completion, ) { @@ -854,11 +848,7 @@ fn complete_rebuild_loader_network_command( return CommandOutputPlan::error(-32000, "InvalidNetworkCommandCompletion"); } }; - match conn.finish_rebuild_resource_runtime_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - completion, - ) { + match conn.finish_rebuild_resource_runtime_for_owner(&owner_scope, completion) { Ok(()) => CommandOutputPlan::success(), Err(error) => CommandOutputPlan::error(-32000, error), } @@ -872,17 +862,9 @@ fn network_page_configuration_will_be_replayed( let Some(dispatched_attachment) = dispatched_attachment else { return false; }; - let owner_still_exists = conn - .target_owner_identity_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) - .is_some(); + let owner_still_exists = conn.target_owner_identity_for_owner(owner_scope).is_some(); let current_attachment = conn - .loaded_page_mut_for_target_configuration_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) + .loaded_page_mut_for_target_configuration_for_owner(owner_scope) .ok() .and_then(|page| page.renderer_agent_attachment_id()); owner_still_exists && current_attachment != Some(dispatched_attachment) diff --git a/moli-protocol/src/domains/network/activity.rs b/moli-protocol/src/domains/network/activity.rs index c8c8e9c913..85d2aa5507 100644 --- a/moli-protocol/src/domains/network/activity.rs +++ b/moli-protocol/src/domains/network/activity.rs @@ -407,10 +407,7 @@ impl NetworkOutputProjectionStep { .and_then(NetworkPreparedOutputSlot::take_subresource_fetch_pauses) { let mut events = Vec::new(); - let network_session_ids = conn.network_event_session_ids_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let network_session_ids = conn.network_event_session_ids_for_owner(&owner); fetch::emit_subresource_fetch_pause_outputs( conn, &mut events, @@ -472,13 +469,9 @@ pub(in crate::domains) fn network_backlog_prepared_outputs_for_owner( ) -> NetworkPreparedOutputs { let mut outputs = NetworkPreparedOutputs::default(); let session_id = owner.session_id(); - let primary_session_id = conn.runtime_session_owner_primary_session_id_for_route( - session_id, - owner.session_owner_route(), - ); - if let Some(backlog) = conn.network_backlog_prepared_delivery_for_route( - session_id, - owner.session_owner_route(), + let primary_session_id = conn.runtime_session_owner_primary_session_id_for_owner(owner); + if let Some(backlog) = conn.network_backlog_prepared_delivery_for_owner( + owner, session_id, primary_session_id.as_deref(), preferred_request_id, @@ -613,9 +606,8 @@ mod tests { request_stage_chain: None, }; assert!( - conn.register_in_flight_subresource_fetch_request_for_route( - Some("SID-1"), - None, + conn.register_in_flight_subresource_fetch_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), Some("fetch-req-1".to_owned()), pending, ), @@ -694,9 +686,8 @@ mod tests { .target_page_residence_identity_for_session(Some("SID-collision")) .expect("old Page residence should exist"); let reused_handle = SubresourceNetworkRequestHandle::new(9); - assert!(conn.register_in_flight_subresource_fetch_request_for_route( - Some("SID-collision"), - None, + assert!(conn.register_in_flight_subresource_fetch_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-collision"), Some("FETCH-old".to_owned()), pending_request_for_page(old_owner, 7, "NETWORK-old", reused_handle), )); @@ -730,9 +721,8 @@ mod tests { let replacement_owner = conn .target_page_residence_identity_for_session(Some("SID-collision")) .expect("replacement Page residence should exist"); - assert!(conn.register_in_flight_subresource_fetch_request_for_route( - Some("SID-collision"), - None, + assert!(conn.register_in_flight_subresource_fetch_request_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-collision"), Some("FETCH-new".to_owned()), pending_request_for_page(replacement_owner, 7, "NETWORK-new", reused_handle), )); @@ -752,8 +742,11 @@ mod tests { "stale continuation must not project an event for the replacement request" ); assert_eq!( - conn.in_flight_subresource_fetch_request_id_for_route(Some("SID-collision"), None, 7,) - .as_deref(), + conn.in_flight_subresource_fetch_request_id_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-collision"), + 7, + ) + .as_deref(), Some("FETCH-new"), "stale apply must not claim the replacement request even when both renderer IDs collide" ); diff --git a/moli-protocol/src/domains/network/backlog.rs b/moli-protocol/src/domains/network/backlog.rs index ac7069cf53..5c34c44736 100644 --- a/moli-protocol/src/domains/network/backlog.rs +++ b/moli-protocol/src/domains/network/backlog.rs @@ -219,9 +219,7 @@ fn emit_complete_subresource_network_delivery_record( let record_document_url = output.document_url(); let timestamp = base_timestamp + ((output.index() + 1) as f64 * 0.000_001); let resource_type = output.resource_type().into(); - let Ok(runtime_slot) = conn - .runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) - else { + let Ok(runtime_slot) = conn.runtime_session_owner_slot_mut_for_owner(owner) else { return false; }; let request_was_announced_by_fetch_pause = @@ -423,7 +421,7 @@ fn emit_staged_subresource_request_started( let timestamp = base_timestamp + ((output.index() + 1) as f64 * 0.000_001); let resource_type = output.resource_type().into(); let request_was_announced_by_fetch_pause = conn - .runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) + .runtime_session_owner_slot_mut_for_owner(owner) .is_ok_and(|runtime_slot| runtime_slot.take_fetch_pause_announced_request_id(request_id)); if output.resource_type() != moli_core::page::SubresourceResourceType::WebSocket { record_subresource_pending_response_body(conn, owner, request_id, event_session_ids); @@ -551,11 +549,7 @@ fn emit_staged_subresource_response_started( ); let fetch_request_id = (!blocked_intercepts.is_empty()) .then(|| { - conn.in_flight_subresource_fetch_request_id_for_route( - owner.session_id(), - owner.session_owner_route(), - output.handle().get(), - ) + conn.in_flight_subresource_fetch_request_id_for_owner(owner, output.handle().get()) }) .flatten(); emit_response_received( @@ -589,12 +583,9 @@ fn matching_subresource_network_intercepts( resource_type: DevToolsNetworkResourceType, url: &url::Url, ) -> Vec { - conn.target_fetch_subresource_interception_snapshot_for_route( - owner.session_id(), - owner.session_owner_route(), - ) - .map(|snapshot| snapshot.matching_network_intercepts(request_stage, resource_type, url)) - .unwrap_or_default() + conn.target_fetch_subresource_interception_snapshot_for_owner(owner) + .map(|snapshot| snapshot.matching_network_intercepts(request_stage, resource_type, url)) + .unwrap_or_default() } fn emit_staged_subresource_body_finished( @@ -714,15 +705,11 @@ pub(crate) fn emit_pending_network_backlog_activity_background_events( preferred_request_id, prepared_outputs, } = context; - let primary_session_id = conn.runtime_session_owner_primary_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let primary_session_id = conn.runtime_session_owner_primary_session_id_for_owner(&owner); let Some((frame_id, snapshot)) = (|| { - let frame_id = frame_id.map(str::to_owned).or_else(|| { - conn.target_owner_identity_for_route(owner.session_id(), owner.session_owner_route())? - .1 - })?; + let frame_id = frame_id + .map(str::to_owned) + .or_else(|| conn.target_owner_identity_for_owner(&owner)?.1)?; let snapshot = pending_network_backlog_delivery_snapshot( conn, &owner, @@ -757,13 +744,10 @@ pub(crate) fn emit_prepared_renderer_network_live_background_events( owner: &CommandOwnerScope, prepared: &mut TargetNetworkBacklogPreparedDelivery, ) { - let session_id = owner.session_id(); let Some((frame_id, snapshot)) = (|| { - let frame_id = conn - .target_owner_identity_for_route(session_id, owner.session_owner_route())? - .1?; + let frame_id = conn.target_owner_identity_for_owner(owner)?.1?; let snapshot = conn - .runtime_session_owner_slot_mut_for_route(session_id, owner.session_owner_route()) + .runtime_session_owner_slot_mut_for_owner(owner) .ok()? .pending_network_backlog_delivery_snapshot_from_backlog(prepared)?; Some((frame_id, snapshot)) @@ -822,19 +806,13 @@ fn pending_network_backlog_delivery_snapshot( prepared_network_outputs: Option<&mut NetworkPreparedOutputs>, ) -> Option { if let Some(prepared_network_outputs) = prepared_network_outputs { - let runtime_slot = conn - .runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - ) - .ok()?; + let runtime_slot = conn.runtime_session_owner_slot_mut_for_owner(owner).ok()?; return runtime_slot.pending_network_backlog_delivery_snapshot_from_backlog( prepared_network_outputs.backlog_mut(), ); } - conn.pending_network_backlog_delivery_snapshot_for_route( - owner.session_id(), - owner.session_owner_route(), + conn.pending_network_backlog_delivery_snapshot_for_owner( + owner, owner.session_id(), primary_session_id, preferred_request_id, @@ -846,9 +824,7 @@ fn mark_network_backlog_delivery_snapshot_emitted( owner: &CommandOwnerScope, snapshot: &PendingNetworkBacklogDeliverySnapshot, ) { - let Ok(runtime_slot) = conn - .runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) - else { + let Ok(runtime_slot) = conn.runtime_session_owner_slot_mut_for_owner(owner) else { return; }; runtime_slot.mark_network_backlog_delivery_snapshot_emitted(snapshot); @@ -863,12 +839,8 @@ fn record_subresource_response_body_source( ) { let captured_body = crate::conn::CapturedBody::from_subresource_response_body(response_body); let data_type = crate::devtools_runtime::DevToolsNetworkDataType::Response; - let collector_ids = conn.network_data_collector_ids_for_route_body( - owner.session_id(), - owner.session_owner_route(), - data_type, - captured_body.len(), - ); + let collector_ids = + conn.network_data_collector_ids_for_owner_body(owner, data_type, captured_body.len()); let collection_was_gated = conn.network_data_collection_is_gated_for_body(data_type); conn.record_collected_network_data_body( request_id.to_owned(), @@ -877,9 +849,7 @@ fn record_subresource_response_body_source( collector_ids.iter().cloned(), collection_was_gated, ); - let Ok(runtime_slot) = conn - .runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) - else { + let Ok(runtime_slot) = conn.runtime_session_owner_slot_mut_for_owner(owner) else { return; }; runtime_slot.record_captured_response_body_source_with_collector_scope( @@ -902,12 +872,8 @@ fn record_subresource_request_body( return; }; let data_type = crate::devtools_runtime::DevToolsNetworkDataType::Request; - let collector_ids = conn.network_data_collector_ids_for_route_body( - owner.session_id(), - owner.session_owner_route(), - data_type, - request_body.len(), - ); + let collector_ids = + conn.network_data_collector_ids_for_owner_body(owner, data_type, request_body.len()); let collection_was_gated = conn.network_data_collection_is_gated_for_body(data_type); conn.record_collected_network_data_body( request_id.to_owned(), @@ -916,9 +882,7 @@ fn record_subresource_request_body( collector_ids.iter().cloned(), collection_was_gated, ); - let Ok(runtime_slot) = conn - .runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) - else { + let Ok(runtime_slot) = conn.runtime_session_owner_slot_mut_for_owner(owner) else { return; }; runtime_slot.record_captured_request_body_with_collector_scope( @@ -936,18 +900,15 @@ fn record_subresource_pending_response_body( request_id: &str, session_ids: &[Option], ) { - let collector_ids = conn.network_data_collector_ids_for_route_body( - owner.session_id(), - owner.session_owner_route(), + let collector_ids = conn.network_data_collector_ids_for_owner_body( + owner, crate::devtools_runtime::DevToolsNetworkDataType::Response, 0, ); let collection_was_gated = conn.network_data_collection_is_gated_for_body( crate::devtools_runtime::DevToolsNetworkDataType::Response, ); - let Ok(runtime_slot) = conn - .runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) - else { + let Ok(runtime_slot) = conn.runtime_session_owner_slot_mut_for_owner(owner) else { return; }; runtime_slot.record_pending_response_body_with_collector_scope( @@ -965,18 +926,15 @@ fn record_subresource_failed_response_body( request_id: &str, session_ids: &[Option], ) { - let collector_ids = conn.network_data_collector_ids_for_route_body( - owner.session_id(), - owner.session_owner_route(), + let collector_ids = conn.network_data_collector_ids_for_owner_body( + owner, crate::devtools_runtime::DevToolsNetworkDataType::Response, 0, ); let collection_was_gated = conn.network_data_collection_is_gated_for_body( crate::devtools_runtime::DevToolsNetworkDataType::Response, ); - let Ok(runtime_slot) = conn - .runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) - else { + let Ok(runtime_slot) = conn.runtime_session_owner_slot_mut_for_owner(owner) else { return; }; runtime_slot.record_failed_response_body_with_collector_scope( diff --git a/moli-protocol/src/domains/network/load_resource.rs b/moli-protocol/src/domains/network/load_resource.rs index 369edcd48a..c54dad0e31 100644 --- a/moli-protocol/src/domains/network/load_resource.rs +++ b/moli-protocol/src/domains/network/load_resource.rs @@ -103,10 +103,7 @@ pub(super) fn complete_network_resource_preparation( } }; let preparation = match conn - .loaded_page_mut_for_protocol_access_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) + .loaded_page_mut_for_protocol_access_for_owner(&owner_scope) .and_then(|page| { if page.renderer_agent_attachment_id() != completion.renderer_agent_attachment_id() { return Err("Document changed while preparing the network resource load".to_owned()); @@ -177,9 +174,8 @@ pub(super) fn complete_network_resource_fetch( Some(headers), ); } - let stream = match conn.open_io_stream_body_source_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), + let stream = match conn.open_io_stream_body_source_for_owner( + &owner_scope, CapturedBody::from_bytes_spooled(response.body), ) { Ok(stream) => stream, diff --git a/moli-protocol/src/domains/network/tests/session.rs b/moli-protocol/src/domains/network/tests/session.rs index 154bf4eff2..d7d1e76f7e 100644 --- a/moli-protocol/src/domains/network/tests/session.rs +++ b/moli-protocol/src/domains/network/tests/session.rs @@ -51,7 +51,10 @@ async fn network_configuration_commands_succeed_while_the_target_is_changing_doc let mut ctx = TestContext::new(); install_network_session_page(&mut ctx, "data:text/html,committed").await; ctx.conn - .start_document_navigation_for_route(Some("SID-navigation"), None, "LID-pending".to_owned()) + .start_document_navigation_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-navigation"), + "LID-pending".to_owned(), + ) .expect("the replacement navigation should start"); ctx.process_async(json!({ diff --git a/moli-protocol/src/domains/observable_output/presence.rs b/moli-protocol/src/domains/observable_output/presence.rs index 311ee2f44b..f0eeed3b9f 100644 --- a/moli-protocol/src/domains/observable_output/presence.rs +++ b/moli-protocol/src/domains/observable_output/presence.rs @@ -130,14 +130,12 @@ pub(in crate::domains) fn inspector_issue_prepared_outputs( owner: &CommandOwnerScope, ) -> ObservablePreparedOutputs { let mut prepared = ObservablePreparedOutputs::default(); - let session_id = owner.session_id(); - let owner_route = owner.session_owner_route(); // Inspector issues are Document facts. Resolve them only against the // exact committed Document captured by the renderer; otherwise a late // issue from a retired generation could be stored and replayed as if it // belonged to its replacement. let Some(document_binding) = conn - .runtime_session_owner_slot_for_route(session_id, owner_route) + .runtime_session_owner_slot_for_owner(owner) .ok() .and_then(|slot| slot.committed_renderer_document_binding()) else { @@ -149,14 +147,12 @@ pub(in crate::domains) fn inspector_issue_prepared_outputs( let page_attachment_id = document_binding.page_attachment_id; let frame_id = document_binding.frame_id.clone(); let loader_id = document_binding.loader_id.clone(); - let Some(storage) = - conn.with_target_owner_state_for_route_mut(session_id, owner_route, |owner_state| { - owner_state - .audits_storage_state - .append_concrete_issue(issue); - owner_state.audits_storage_state.clone() - }) - else { + let Some(storage) = conn.with_target_owner_state_for_owner_mut(owner, |owner_state| { + owner_state + .audits_storage_state + .append_concrete_issue(issue); + owner_state.audits_storage_state.clone() + }) else { return prepared; }; @@ -164,11 +160,13 @@ pub(in crate::domains) fn inspector_issue_prepared_outputs( // then fans out to every enabled frontend session. Each session keeps its // own cursor, matching Blink's per-session Audits agent state without // rediscovering the issue from a later Page snapshot. - for event_session_id in conn.page_event_session_ids_for_route(session_id, owner_route) { + for event_session_id in conn.page_event_session_ids_for_owner(owner) { let event_session_id = event_session_id.as_deref(); - let event_owner_route = event_session_id.is_none().then_some(owner_route).flatten(); + let event_owner = event_session_id + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); let Some(cursor) = conn - .target_page_session_state_for_route(event_session_id, event_owner_route) + .target_page_session_state_for_owner(&event_owner) .and_then(|state| state.audits.pending_cursor(&storage)) else { continue; @@ -232,50 +230,44 @@ fn push_runtime_observable_tail_prepared_outputs( deliver_log_to_enabled_sessions: bool, runtime_audience: RuntimeObservableAudience, ) { - let session_id = owner.session_id(); - let owner_route = owner.session_owner_route(); let owner_state = conn - .target_owner_state_for_route(session_id, owner_route) + .target_owner_state_for_owner(owner) .cloned() .unwrap_or_default(); - let include_console_api_messages = - !renderer_agent_owns_page_console_api_events(conn, session_id, owner_route); + let include_console_api_messages = !renderer_agent_owns_page_console_api_events(conn, owner); push_console_log_source_prepared_outputs( prepared, conn, source, - session_id, + owner, &owner_state, include_console_api_messages, deliver_log_to_enabled_sessions, - owner_route, ); let attachments = match runtime_audience { RuntimeObservableAudience::SourceSession => conn - .target_page_protocol_attachment_identity_for_route(session_id, owner_route) + .target_page_protocol_attachment_identity_for_owner(owner) .into_iter() .collect(), RuntimeObservableAudience::EnabledTargetAttachments => conn - .runtime_event_protocol_attachments_for_route(session_id, owner_route) + .runtime_event_protocol_attachments_for_owner(owner) .unwrap_or_default(), }; for attachment in attachments { let event_session_id = attachment.session_id(); - let event_owner_route = event_session_id.is_none().then_some(owner_route).flatten(); + let event_owner = event_session_id + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); if !conn - .target_runtime_session_state_for_route(event_session_id, event_owner_route) + .target_runtime_session_state_for_owner(&event_owner) .is_some_and(|state| state.runtime_frontend_enabled) { continue; } let include_runtime_console_api_messages = - !renderer_runtime_agent_owns_page_console_api_events( - conn, - event_session_id, - event_owner_route, - ); + !renderer_runtime_agent_owns_page_console_api_events(conn, &event_owner); if let Some(items) = source.source_items_prepared_for_state( &owner_state.runtime_observable_state, include_runtime_console_api_messages, @@ -289,16 +281,13 @@ fn push_console_log_source_prepared_outputs( prepared: &mut ObservablePreparedOutputs, conn: &CdpConnection, source: &super::TargetRuntimeObservableSourceOutput, - session_id: Option<&str>, + owner: &CommandOwnerScope, owner_state: &crate::conn::TargetOwnerState, include_console_api_messages: bool, deliver_log_to_enabled_sessions: bool, - owner_route: Option<&crate::conn::CdpSessionRoute>, ) { let queue = TargetObservableOutputQueue::from_runtime_source_output_ref(Some(source)); - if let Some(devtools_session_state) = - conn.target_devtools_session_state_for_route(session_id, owner_route) - { + if let Some(devtools_session_state) = conn.target_devtools_session_state_for_owner(owner) { prepared.extend( queue.console_log_backlog_ranges( source.url(), @@ -310,7 +299,7 @@ fn push_console_log_source_prepared_outputs( include_console_api_messages, owner_state, &devtools_session_state.console_output_session_state, - session_id, + owner.session_id(), ), ); } @@ -329,30 +318,27 @@ fn push_console_log_source_prepared_outputs( source.url(), source.page_attachment_id(), owner_state, - session_id, - owner_route, + owner, ); } fn renderer_agent_owns_page_console_api_events( conn: &CdpConnection, - session_id: Option<&str>, - owner_route: Option<&crate::conn::CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> bool { - if session_id.is_some_and(|session_id| { + if owner.session_id().is_some_and(|session_id| { conn.shared_worker_target_for_session(Some(session_id)) .is_some() }) { return false; } - let Ok(runtime_slot) = conn.runtime_session_owner_slot_for_route(session_id, owner_route) - else { + let Ok(runtime_slot) = conn.runtime_session_owner_slot_for_owner(owner) else { return false; }; if !runtime_slot.has_loaded_page() { return false; } - conn.target_devtools_session_state_for_route(session_id, owner_route) + conn.target_devtools_session_state_for_owner(owner) .is_some_and(|state| { state .console_output_session_state @@ -362,23 +348,21 @@ fn renderer_agent_owns_page_console_api_events( fn renderer_runtime_agent_owns_page_console_api_events( conn: &CdpConnection, - session_id: Option<&str>, - owner_route: Option<&crate::conn::CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> bool { - if session_id.is_some_and(|session_id| { + if owner.session_id().is_some_and(|session_id| { conn.shared_worker_target_for_session(Some(session_id)) .is_some() }) { return false; } - let Ok(runtime_slot) = conn.runtime_session_owner_slot_for_route(session_id, owner_route) - else { + let Ok(runtime_slot) = conn.runtime_session_owner_slot_for_owner(owner) else { return false; }; if !runtime_slot.has_loaded_page() { return false; } - conn.target_devtools_session_state_for_route(session_id, owner_route) + conn.target_devtools_session_state_for_owner(owner) .is_some_and(|state| { state .console_output_session_state @@ -402,13 +386,8 @@ fn runtime_console_source_tail_for_owner( message: RuntimeConsoleMessageSnapshot, owner: &CommandOwnerScope, ) -> Option { - let url = conn.runtime_session_owner_target_url_for_route( - owner.session_id(), - owner.session_owner_route(), - )?; - let runtime_slot = conn - .runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) - .ok()?; + let url = conn.runtime_session_owner_target_url_for_owner(owner)?; + let runtime_slot = conn.runtime_session_owner_slot_mut_for_owner(owner).ok()?; runtime_slot.append_renderer_runtime_console_message(url, message) } @@ -418,13 +397,8 @@ fn runtime_lifecycle_error_source_tail_for_owner( execution_context_id: Option, owner: &CommandOwnerScope, ) -> Option { - let url = conn.runtime_session_owner_target_url_for_route( - owner.session_id(), - owner.session_owner_route(), - )?; - let runtime_slot = conn - .runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) - .ok()?; + let url = conn.runtime_session_owner_target_url_for_owner(owner)?; + let runtime_slot = conn.runtime_session_owner_slot_mut_for_owner(owner).ok()?; runtime_slot.append_renderer_runtime_lifecycle_error(url, text, execution_context_id) } @@ -454,19 +428,14 @@ pub(in crate::domains) fn live_log_prepared_outputs_for_renderer_network_fact( conn: &CdpConnection, owner: &CommandOwnerScope, ) -> ObservablePreparedOutputs { - let session_id = owner.session_id(); - let owner_route = owner.session_owner_route(); let owner_state = conn - .target_owner_state_for_route(session_id, owner_route) + .target_owner_state_for_owner(owner) .cloned() .unwrap_or_default(); - let Some(runtime_slot) = conn - .runtime_session_owner_slot_for_route(session_id, owner_route) - .ok() - else { + let Some(runtime_slot) = conn.runtime_session_owner_slot_for_owner(owner).ok() else { return ObservablePreparedOutputs::default(); }; - let Some(url) = conn.runtime_session_owner_target_url_for_route(session_id, owner_route) else { + let Some(url) = conn.runtime_session_owner_target_url_for_owner(owner) else { return ObservablePreparedOutputs::default(); }; let Some(queue) = TargetObservableOutputQueue::from_log_storage(runtime_slot) else { @@ -483,8 +452,7 @@ pub(in crate::domains) fn live_log_prepared_outputs_for_renderer_network_fact( &url, page_attachment_id, &owner_state, - session_id, - owner_route, + owner, ); prepared } @@ -504,8 +472,10 @@ fn observable_console_log_prepared_outputs_for_session_owner( let url = conn.runtime_session_owner_target_url(session_id)?; let queue = super::output_queue::TargetObservableOutputQueue::from_runtime_slot(runtime_slot)?; let page_attachment_id = runtime_slot.page_attachment_id()?; - let include_console_api_messages = - !renderer_agent_owns_page_console_api_events(conn, session_id, None); + let include_console_api_messages = !renderer_agent_owns_page_console_api_events( + conn, + &CommandOwnerScope::capture(conn, session_id), + ); let mut prepared = ObservablePreparedOutputs::default(); if console_allowed @@ -529,6 +499,7 @@ fn observable_console_log_prepared_outputs_for_session_owner( } if log_allowed { + let owner = CommandOwnerScope::capture(conn, session_id); push_log_prepared_outputs_for_enabled_sessions( &mut prepared, conn, @@ -536,8 +507,7 @@ fn observable_console_log_prepared_outputs_for_session_owner( &url, page_attachment_id, &owner_state, - session_id, - None, + &owner, ); } @@ -551,18 +521,19 @@ fn push_log_prepared_outputs_for_enabled_sessions( url: &str, page_attachment_id: crate::conn::TargetPageAttachmentId, owner_state: &crate::conn::TargetOwnerState, - session_id: Option<&str>, - owner_route: Option<&crate::conn::CdpSessionRoute>, + owner: &CommandOwnerScope, ) { // A concrete Page error is stored once but observed by every Log agent // attached to that target. The publication route names one canonical // session only; it must not accidentally turn a target-owned fact into a // single-session event. - for event_session_id in conn.page_event_session_ids_for_route(session_id, owner_route) { + for event_session_id in conn.page_event_session_ids_for_owner(owner) { let event_session_id = event_session_id.as_deref(); - let event_owner_route = event_session_id.is_none().then_some(owner_route).flatten(); + let event_owner = event_session_id + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); let Some(devtools_session_state) = - conn.target_devtools_session_state_for_route(event_session_id, event_owner_route) + conn.target_devtools_session_state_for_owner(&event_owner) else { continue; }; diff --git a/moli-protocol/src/domains/observable_output/runtime_emission.rs b/moli-protocol/src/domains/observable_output/runtime_emission.rs index d9fc50dc18..18c6798ffe 100644 --- a/moli-protocol/src/domains/observable_output/runtime_emission.rs +++ b/moli-protocol/src/domains/observable_output/runtime_emission.rs @@ -23,17 +23,13 @@ pub(in crate::domains) fn advance_runtime_observable_cursors_to_current_for_owne if let Some((context_console_counts, exception_entries)) = runtime_observable_cursor_end_from_owner_queue_for_owner(conn, owner) { - let _ = conn.with_target_owner_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |owner_state| { - owner_state.runtime_observable_state.advance_to_current( - context_console_counts, - 0, - exception_entries, - ); - }, - ); + let _ = conn.with_target_owner_state_for_owner_mut(owner, |owner_state| { + owner_state.runtime_observable_state.advance_to_current( + context_console_counts, + 0, + exception_entries, + ); + }); return; } let Some((owner_queue_console_entries, exception_entries)) = @@ -41,31 +37,22 @@ pub(in crate::domains) fn advance_runtime_observable_cursors_to_current_for_owne else { return; }; - let _ = conn.with_target_owner_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |owner_state| { - owner_state.runtime_observable_state.advance_to_current( - HashMap::new(), - owner_queue_console_entries, - exception_entries, - ); - }, - ); + let _ = conn.with_target_owner_state_for_owner_mut(owner, |owner_state| { + owner_state.runtime_observable_state.advance_to_current( + HashMap::new(), + owner_queue_console_entries, + exception_entries, + ); + }); } fn runtime_observable_cursor_end_from_owner_queue_for_owner( conn: &CdpConnection, owner: &CommandOwnerScope, ) -> Option<(HashMap, usize)> { - let runtime_slot = conn - .runtime_session_owner_slot_for_route(owner.session_id(), owner.session_owner_route()) - .ok()?; + let runtime_slot = conn.runtime_session_owner_slot_for_owner(owner).ok()?; let source = runtime_slot.observable_output_latest_source_tail()?; - let url = conn.runtime_session_owner_target_url_for_route( - owner.session_id(), - owner.session_owner_route(), - )?; + let url = conn.runtime_session_owner_target_url_for_owner(owner)?; (source.url() == url && runtime_slot.page_attachment_id() == Some(source.page_attachment_id())) .then_some(source)? .cursor_end() @@ -75,7 +62,7 @@ fn runtime_observable_cursor_end_from_owner_observable_queue_for_owner( conn: &CdpConnection, owner: &CommandOwnerScope, ) -> Option<(usize, usize)> { - conn.runtime_session_owner_slot_for_route(owner.session_id(), owner.session_owner_route()) + conn.runtime_session_owner_slot_for_owner(owner) .ok()? .observable_output_cursor_end() } diff --git a/moli-protocol/src/domains/page.rs b/moli-protocol/src/domains/page.rs index e9c505e0c1..e259502bb6 100644 --- a/moli-protocol/src/domains/page.rs +++ b/moli-protocol/src/domains/page.rs @@ -517,22 +517,19 @@ impl PagePreparedOutputs { owner: &CommandOwnerScope, dialog: moli_core::page::RendererPendingJavaScriptDialog, ) -> Self { - let session_id = owner.session_id(); - let owner_route = owner.session_owner_route(); let Some(source_attachment) = - conn.target_page_protocol_attachment_identity_for_route(session_id, owner_route) + conn.target_page_protocol_attachment_identity_for_owner(owner) else { let _ = dialog.finish(false, String::new()); return Self::default(); }; let Some((root_frame_id, _, _, _)) = - conn.target_session_owner_frame_tree_identity_for_route(session_id, owner_route) + conn.target_session_owner_frame_tree_identity_for_owner(owner) else { let _ = dialog.finish(false, String::new()); return Self::default(); }; - let Ok(runtime_slot) = conn.runtime_session_owner_slot_for_route(session_id, owner_route) - else { + let Ok(runtime_slot) = conn.runtime_session_owner_slot_for_owner(owner) else { let _ = dialog.finish(false, String::new()); return Self::default(); }; @@ -552,10 +549,7 @@ impl PagePreparedOutputs { owner: &CommandOwnerScope, activation: moli_core::page::RendererPendingPopupActivation, ) -> Self { - let Some(page_owner) = conn.target_page_residence_identity_for_route( - owner.session_id(), - owner.session_owner_route(), - ) else { + let Some(page_owner) = conn.target_page_residence_identity_for_owner(owner) else { return Self::default(); }; Self { @@ -573,10 +567,7 @@ impl PagePreparedOutputs { ) -> Self { Self { window_open_events: vec![popup::PagePreparedWindowOpenEvent::new( - conn.subscribed_page_event_session_ids_for_route( - owner.session_id(), - owner.session_owner_route(), - ), + conn.subscribed_page_event_session_ids_for_owner(owner), event, )], ..Self::default() @@ -588,10 +579,7 @@ impl PagePreparedOutputs { owner: &CommandOwnerScope, navigation: RendererDocumentSourcedSameDocumentNavigation, ) -> Self { - let Some(page_owner) = conn.target_page_residence_identity_for_route( - owner.session_id(), - owner.session_owner_route(), - ) else { + let Some(page_owner) = conn.target_page_residence_identity_for_owner(owner) else { return Self::default(); }; Self { @@ -607,10 +595,7 @@ impl PagePreparedOutputs { owner: &CommandOwnerScope, navigation: RendererDocumentSourcedTopLevelLocationNavigation, ) -> Self { - let Some(page_owner) = conn.target_page_residence_identity_for_route( - owner.session_id(), - owner.session_owner_route(), - ) else { + let Some(page_owner) = conn.target_page_residence_identity_for_owner(owner) else { return Self::default(); }; Self { @@ -636,17 +621,13 @@ impl PagePreparedOutputs { source_document: RendererDocumentLifecycleIdentity, event: ChildFrameTreeEventSnapshot, ) -> Self { - let session_id = owner.session_id(); - let owner_route = owner.session_owner_route(); - let Some(binding) = conn.target_root_document_protocol_attachment_identity_for_route( - session_id, - owner_route, - source_document, - ) else { + let Some(binding) = conn + .target_root_document_protocol_attachment_identity_for_owner(owner, source_document) + else { return Self::default(); }; let Some((root_frame_id, _, security_origin, secure_context_type)) = - conn.target_session_owner_frame_tree_identity_for_route(session_id, owner_route) + conn.target_session_owner_frame_tree_identity_for_owner(owner) else { return Self::default(); }; @@ -686,17 +667,13 @@ impl PagePreparedOutputs { source_document: RendererDocumentLifecycleIdentity, mut event: ChildFrameDocumentOpenedSnapshot, ) -> Self { - let session_id = owner.session_id(); - let owner_route = owner.session_owner_route(); - let Some(binding) = conn.target_root_document_protocol_attachment_identity_for_route( - session_id, - owner_route, - source_document, - ) else { + let Some(binding) = conn + .target_root_document_protocol_attachment_identity_for_owner(owner, source_document) + else { return Self::default(); }; let Some((root_frame_id, _, security_origin, secure_context_type)) = - conn.target_session_owner_frame_tree_identity_for_route(session_id, owner_route) + conn.target_session_owner_frame_tree_identity_for_owner(owner) else { return Self::default(); }; @@ -726,17 +703,13 @@ impl PagePreparedOutputs { source_document: RendererDocumentLifecycleIdentity, event: ChildFrameDocumentNetworkActivitySnapshot, ) -> Self { - let session_id = owner.session_id(); - let owner_route = owner.session_owner_route(); - let Some(binding) = conn.target_root_document_protocol_attachment_identity_for_route( - session_id, - owner_route, - source_document, - ) else { + let Some(binding) = conn + .target_root_document_protocol_attachment_identity_for_owner(owner, source_document) + else { return Self::default(); }; let Some((_, _, security_origin, secure_context_type)) = - conn.target_session_owner_frame_tree_identity_for_route(session_id, owner_route) + conn.target_session_owner_frame_tree_identity_for_owner(owner) else { return Self::default(); }; @@ -763,17 +736,13 @@ impl PagePreparedOutputs { source_document: RendererDocumentLifecycleIdentity, mut event: ChildFrameNavigationSnapshot, ) -> Self { - let session_id = owner.session_id(); - let owner_route = owner.session_owner_route(); - let Some(binding) = conn.target_root_document_protocol_attachment_identity_for_route( - session_id, - owner_route, - source_document, - ) else { + let Some(binding) = conn + .target_root_document_protocol_attachment_identity_for_owner(owner, source_document) + else { return Self::default(); }; let Some((root_frame_id, _, security_origin, secure_context_type)) = - conn.target_session_owner_frame_tree_identity_for_route(session_id, owner_route) + conn.target_session_owner_frame_tree_identity_for_owner(owner) else { return Self::default(); }; @@ -1222,7 +1191,7 @@ impl PageOutputProjectionStep { input::emit_download_activity_background_events_async( conn, &mut events, - owner.session_id(), + &owner, prepared_outputs, context.command, ) @@ -1260,16 +1229,13 @@ impl PageOutputProjectionStep { let mut events = Vec::new(); for change in changes { if conn - .apply_renderer_document_title_for_session_owner( - owner.session_id(), - &change, - ) + .apply_renderer_document_title_for_owner(&owner, &change) .unwrap_or(false) { - crate::domains::target::emit_target_info_changed_for_session_owner_background_event( + crate::domains::target::emit_target_info_changed_for_owner_background_event( conn, &mut events, - owner.session_id(), + &owner, ); } } @@ -1281,7 +1247,7 @@ impl PageOutputProjectionStep { input::emit_file_chooser_activity_background_events_async( conn, &mut events, - owner.session_id(), + &owner, prepared_outputs, ) .await; @@ -1292,7 +1258,6 @@ impl PageOutputProjectionStep { emit_javascript_dialog_activity_background_events_async( conn, &mut events, - owner.session_id(), prepared_outputs, ) .await; @@ -1313,13 +1278,8 @@ impl PageOutputProjectionStep { } PageOutputProjectionStep::Popup => { let mut events = Vec::new(); - emit_popup_activity_background_events_async( - conn, - &mut events, - owner.session_id(), - prepared_outputs, - ) - .await; + emit_popup_activity_background_events_async(conn, &mut events, prepared_outputs) + .await; context.command.protocol_events_mut().extend(events); } PageOutputProjectionStep::ChildFrameActivity => { @@ -1339,7 +1299,7 @@ impl PageOutputProjectionStep { emit_same_document_navigation_activity_background_events_async( conn, &mut events, - owner.session_id(), + &owner, prepared_outputs, ) .await; @@ -1348,7 +1308,7 @@ impl PageOutputProjectionStep { PageOutputProjectionStep::TopLevelLocationNavigation => { publish_prepared_top_level_location_navigation_owner_action( conn, - owner.session_id(), + &owner, prepared_outputs, ); } @@ -1357,7 +1317,7 @@ impl PageOutputProjectionStep { emit_top_level_history_traversal_activity_background_events_async( conn, &mut events, - owner.session_id(), + &owner, prepared_outputs, ) .await; @@ -1910,10 +1870,9 @@ impl CdpConnection { &mut self, registration: &PageScreencastRegistration, ) -> PageScreencastSubscriptionStatus { - page_screencast_subscription_status_for_route( + page_screencast_subscription_status_for_owner( self, - registration.session_id(), - registration.owner_scope.session_owner_route(), + ®istration.owner_scope, registration.generation, ) } @@ -1926,25 +1885,19 @@ impl CdpConnection { let session_id = registration.session_id().map(str::to_owned); let generation = registration.generation; let owner_scope = registration.owner_scope.clone(); - let session_id_ref = session_id.as_deref(); - let owner_route = owner_scope.session_owner_route(); - if page_screencast_subscription_status_for_route( - self, - session_id_ref, - owner_route, - generation, - ) != PageScreencastSubscriptionStatus::Ready + if page_screencast_subscription_status_for_owner(self, &owner_scope, generation) + != PageScreencastSubscriptionStatus::Ready { return PageScreencastCaptureStart::Stale; } let Some(config) = self - .target_page_session_state_for_route(session_id_ref, owner_route) + .target_page_session_state_for_owner(&owner_scope) .and_then(|state| state.page_screencast.config()) .cloned() else { return PageScreencastCaptureStart::Stale; }; - let viewport = current_viewport_surface_for_route(self, session_id_ref, owner_route); + let viewport = current_viewport_surface_for_owner(self, &owner_scope); let request = RendererCaptureScreencastFrameRequest { format: match config.format() { PageScreencastFormat::Png => RendererScreenshotFormat::Png, @@ -1956,20 +1909,17 @@ impl CdpConnection { max_height: config.max_height(), known_visual_state, }; - let pending = - match self.loaded_page_mut_for_protocol_access_for_route(session_id_ref, owner_route) { - Ok(page) => match page.start_capture_screencast_frame(request) { - Ok(pending) => pending, - Err(error) => { - tracing::debug!(?error, "failed to start screencast frame capture"); - return PageScreencastCaptureStart::Retry; - } - }, - Err(_) => return PageScreencastCaptureStart::Retry, - }; - if self.begin_page_screencast_capture_for_route(session_id_ref, owner_route, generation) - != Some(true) - { + let pending = match self.loaded_page_mut_for_protocol_access_for_owner(&owner_scope) { + Ok(page) => match page.start_capture_screencast_frame(request) { + Ok(pending) => pending, + Err(error) => { + tracing::debug!(?error, "failed to start screencast frame capture"); + return PageScreencastCaptureStart::Retry; + } + }, + Err(_) => return PageScreencastCaptureStart::Retry, + }; + if self.begin_page_screencast_capture_for_owner(&owner_scope, generation) != Some(true) { tracing::debug!( generation, ?session_id, @@ -1998,27 +1948,19 @@ impl CdpConnection { completed, } = completed; let session_id_ref = session_id.as_deref(); - let owner_route = owner_scope.session_owner_route(); - if page_screencast_subscription_status_for_route( - self, - session_id_ref, - owner_route, - generation, - ) != PageScreencastSubscriptionStatus::CaptureInProgress + if page_screencast_subscription_status_for_owner(self, &owner_scope, generation) + != PageScreencastSubscriptionStatus::CaptureInProgress { return PageScreencastCaptureCompletion::Stale; } let frame = match completed { Ok(completion) => { - let page = match self - .loaded_page_mut_for_protocol_access_for_route(session_id_ref, owner_route) - { + let page = match self.loaded_page_mut_for_protocol_access_for_owner(&owner_scope) { Ok(page) => page, Err(_) => { - let _ = self.complete_page_screencast_capture_for_route( - session_id_ref, - owner_route, + let _ = self.complete_page_screencast_capture_for_owner( + &owner_scope, generation, false, ); @@ -2028,9 +1970,8 @@ impl CdpConnection { match page.finish_capture_screencast_frame(*completion) { Ok(RendererCaptureScreencastFrameReply::Captured(frame)) => frame, Ok(RendererCaptureScreencastFrameReply::Unchanged) => { - if self.complete_page_screencast_capture_for_route( - session_id_ref, - owner_route, + if self.complete_page_screencast_capture_for_owner( + &owner_scope, generation, false, ) != Some(true) @@ -2044,9 +1985,8 @@ impl CdpConnection { | RendererCaptureScreencastFrameReply::NoDocument, ) | Err(_) => { - let _ = self.complete_page_screencast_capture_for_route( - session_id_ref, - owner_route, + let _ = self.complete_page_screencast_capture_for_owner( + &owner_scope, generation, false, ); @@ -2055,9 +1995,8 @@ impl CdpConnection { } } Err(_) => { - let _ = self.complete_page_screencast_capture_for_route( - session_id_ref, - owner_route, + let _ = self.complete_page_screencast_capture_for_owner( + &owner_scope, generation, false, ); @@ -2066,12 +2005,8 @@ impl CdpConnection { }; let visual_state = frame.visual_state; - if self.complete_page_screencast_capture_for_route( - session_id_ref, - owner_route, - generation, - true, - ) != Some(true) + if self.complete_page_screencast_capture_for_owner(&owner_scope, generation, true) + != Some(true) { return PageScreencastCaptureCompletion::Stale; } @@ -2099,13 +2034,12 @@ impl CdpConnection { } } -fn page_screencast_subscription_status_for_route( +fn page_screencast_subscription_status_for_owner( conn: &CdpConnection, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, generation: i32, ) -> PageScreencastSubscriptionStatus { - let Some(state) = conn.target_page_session_state_for_route(session_id, owner_route) else { + let Some(state) = conn.target_page_session_state_for_owner(owner) else { return PageScreencastSubscriptionStatus::Inactive; }; let screencast = &state.page_screencast; @@ -2160,7 +2094,11 @@ fn complete_devtools_handle_javascript_dialog_command( conn: &mut CdpConnection, command: DevToolsHandleJavaScriptDialogCommand, ) -> CommandOutputPlan { - match finish_devtools_handle_javascript_dialog_command(conn, command, None) { + let owner = match page_command_owner(conn, &command.context) { + Ok(owner) => owner, + Err(error) => return CommandOutputPlan::from_devtools_error(error), + }; + match finish_devtools_handle_javascript_dialog_command(conn, command, &owner) { Ok(closed_event) => { let mut plan = CommandOutputPlan::default(); plan.push_background_event(closed_event); @@ -2173,13 +2111,11 @@ fn complete_devtools_handle_javascript_dialog_command( fn finish_devtools_get_javascript_dialog_command( conn: &CdpConnection, - command: DevToolsGetJavaScriptDialogCommand, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Result { - let session_id = command.context.session_id.as_ref().map(|id| id.as_str()); - let current_page_owner = conn.target_page_residence_identity_for_route(session_id, owner_route); + let current_page_owner = conn.target_page_residence_identity_for_owner(owner); let Some(dialog) = conn - .target_page_session_state_for_route(session_id, owner_route) + .target_page_session_state_for_owner(owner) .and_then(|page_state| page_state.javascript_dialog_state.peek_next()) .filter(|dialog| current_page_owner.as_ref() == Some(dialog.page_owner())) else { @@ -2198,37 +2134,34 @@ fn finish_devtools_get_javascript_dialog_command( fn finish_devtools_set_javascript_dialog_prompt_text_command( conn: &mut CdpConnection, command: DevToolsSetJavaScriptDialogPromptTextCommand, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Result { - let session_id = command.context.session_id.as_ref().map(|id| id.as_str()); - let current_page_owner = conn.target_page_residence_identity_for_route(session_id, owner_route); - let Some(result) = - conn.with_target_devtools_session_state_for_route_mut(session_id, owner_route, |state| { - let dialog_state = &mut state.page_session_state.javascript_dialog_state; - let Some(dialog) = dialog_state - .peek_next() - .filter(|dialog| current_page_owner.as_ref() == Some(dialog.page_owner())) - else { - return Err(DevToolsError::new( - DevToolsErrorKind::NoSuchAlert, - "No dialog is showing", - )); - }; - if dialog.dialog_type() != "prompt" { - return Err(DevToolsError::new( - DevToolsErrorKind::InvalidArgument, - "Dialog is not a prompt", - )); - } - if !dialog_state.set_next_prompt_text(command.prompt_text) { - return Err(DevToolsError::new( - DevToolsErrorKind::NoSuchAlert, - "No dialog is showing", - )); - } - Ok(DevToolsCommandResult::Empty) - }) - else { + let current_page_owner = conn.target_page_residence_identity_for_owner(owner); + let Some(result) = conn.with_target_devtools_session_state_for_owner_mut(owner, |state| { + let dialog_state = &mut state.page_session_state.javascript_dialog_state; + let Some(dialog) = dialog_state + .peek_next() + .filter(|dialog| current_page_owner.as_ref() == Some(dialog.page_owner())) + else { + return Err(DevToolsError::new( + DevToolsErrorKind::NoSuchAlert, + "No dialog is showing", + )); + }; + if dialog.dialog_type() != "prompt" { + return Err(DevToolsError::new( + DevToolsErrorKind::InvalidArgument, + "Dialog is not a prompt", + )); + } + if !dialog_state.set_next_prompt_text(command.prompt_text) { + return Err(DevToolsError::new( + DevToolsErrorKind::NoSuchAlert, + "No dialog is showing", + )); + } + Ok(DevToolsCommandResult::Empty) + }) else { return Err(DevToolsError::new( DevToolsErrorKind::NoSuchAlert, "No dialog is showing", @@ -2240,13 +2173,13 @@ fn finish_devtools_set_javascript_dialog_prompt_text_command( fn finish_devtools_handle_javascript_dialog_command( conn: &mut CdpConnection, command: DevToolsHandleJavaScriptDialogCommand, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Result { let session_id = command.context.session_id.as_ref().map(|id| id.as_str()); let command_prompt_text = command.prompt_text; - let current_page_owner = conn.target_page_residence_identity_for_route(session_id, owner_route); + let current_page_owner = conn.target_page_residence_identity_for_owner(owner); let Some(dialog) = conn - .with_target_devtools_session_state_for_route_mut(session_id, owner_route, |state| { + .with_target_devtools_session_state_for_owner_mut(owner, |state| { let dialog_state = &mut state.page_session_state.javascript_dialog_state; if dialog_state .peek_next() @@ -2287,7 +2220,6 @@ fn finish_devtools_handle_javascript_dialog_command( pub(in crate::domains) async fn emit_javascript_dialog_activity_background_events_async( conn: &mut CdpConnection, out: &mut Vec, - _session_id: Option<&str>, prepared_outputs: Option<&mut ProtocolOutputPayloads>, ) { if let Some(dialogs) = prepared_outputs @@ -2301,7 +2233,6 @@ pub(in crate::domains) async fn emit_javascript_dialog_activity_background_event pub(in crate::domains) async fn emit_popup_activity_background_events_async( conn: &mut CdpConnection, out: &mut Vec, - _session_id: Option<&str>, prepared_outputs: Option<&mut ProtocolOutputPayloads>, ) { if let Some(popups) = prepared_outputs @@ -2319,7 +2250,7 @@ pub(in crate::domains) async fn emit_popup_activity_background_events_async( /// would let network/download side effects bypass scheduler predecessors. pub(in crate::domains) fn publish_prepared_top_level_location_navigation_owner_action( conn: &mut CdpConnection, - session_id: Option<&str>, + command_owner: &CommandOwnerScope, prepared_outputs: Option<&mut ProtocolOutputPayloads>, ) { if let Some(navigation) = prepared_outputs @@ -2328,7 +2259,9 @@ pub(in crate::domains) fn publish_prepared_top_level_location_navigation_owner_a { let (owner, navigation) = navigation.into_parts(); conn.publish_prepared_top_level_location_navigation_owner_action( - session_id, owner, navigation, + command_owner, + owner, + navigation, ); } } @@ -2336,7 +2269,7 @@ pub(in crate::domains) fn publish_prepared_top_level_location_navigation_owner_a pub(in crate::domains) async fn emit_top_level_history_traversal_activity_background_events_async( conn: &mut CdpConnection, out: &mut Vec, - session_id: Option<&str>, + owner: &CommandOwnerScope, prepared_outputs: Option<&mut ProtocolOutputPayloads>, ) { if let Some(traversal) = prepared_outputs @@ -2346,7 +2279,7 @@ pub(in crate::domains) async fn emit_top_level_history_traversal_activity_backgr traverse_session_owner_history_from_renderer_background_events_async( conn, out, - session_id, + owner, traversal.delta, ) .await; @@ -2362,7 +2295,7 @@ pub(crate) async fn navigate_page_owned_top_level_location_background_events_asy ) { let session_id = command_owner.session_id(); let source_document = navigation.source_document(); - if !conn.target_page_residence_identity_is_current_for_session(session_id, owner) { + if !conn.target_page_residence_identity_is_current(owner) { tracing::debug!( session_id, ?source_document, @@ -2433,11 +2366,10 @@ async fn navigate_command_owner_from_renderer_request_background_events_async( pub(crate) async fn traverse_session_owner_history_from_renderer_background_events_async( conn: &mut CdpConnection, out: &mut Vec, - session_id: Option<&str>, + owner: &CommandOwnerScope, delta: i64, ) { - let step = - navigation::start_session_owner_history_traversal_from_renderer(conn, session_id, delta); + let step = navigation::start_session_owner_history_traversal_from_renderer(conn, owner, delta); complete_renderer_navigation_step_background_events_async(conn, out, step).await; } @@ -2463,29 +2395,28 @@ async fn complete_renderer_navigation_step_background_events_async( } } -pub(crate) fn emit_page_window_open_background_events_for_route( +pub(crate) fn emit_page_window_open_background_events_for_owner( conn: &CdpConnection, out: &mut Vec, - owner_session_id: Option<&str>, - owner_route: Option<&crate::conn::CdpSessionRoute>, + owner: &CommandOwnerScope, url: &str, window_name: &str, window_features: &[String], user_gesture: bool, ) { - if !crate::domains::target::popup_activation_creates_new_target_for_route( + if !crate::domains::target::popup_activation_creates_new_target_for_owner( conn, - owner_session_id, - owner_route, + owner, window_name, ) { return; } - for event_session_id in conn.page_event_session_ids_for_route(owner_session_id, owner_route) { - let event_owner_route = event_session_id.is_none().then_some(owner_route).flatten(); - if conn.page_domain_enabled_for_route(event_session_id.as_deref(), event_owner_route) - == Some(true) - { + for event_session_id in conn.page_event_session_ids_for_owner(owner) { + let event_owner = event_session_id + .as_deref() + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); + if conn.page_domain_enabled_for_owner(&event_owner) == Some(true) { out.push(BackgroundProtocolEvent::page_window_open( event_session_id.as_deref(), url, @@ -2500,7 +2431,7 @@ pub(crate) fn emit_page_window_open_background_events_for_route( pub(in crate::domains) async fn emit_same_document_navigation_activity_background_events_async( conn: &mut CdpConnection, out: &mut Vec, - session_id: Option<&str>, + owner: &CommandOwnerScope, prepared_outputs: Option<&mut ProtocolOutputPayloads>, ) { if let Some(navigations) = prepared_outputs @@ -2510,7 +2441,7 @@ pub(in crate::domains) async fn emit_same_document_navigation_activity_backgroun navigation::emit_same_document_navigation_background_events_async( conn, out, - session_id, + owner, navigations, ) .await; @@ -2535,7 +2466,9 @@ mod producer_tests { }; use serde_json::{Value, json}; - use crate::conn::{BackgroundProtocolEvent, BrowserContext, CdpConnection, CdpTargetFilter}; + use crate::conn::{ + BackgroundProtocolEvent, BrowserContext, CdpConnection, CdpTargetFilter, CommandOwnerScope, + }; use crate::devtools_runtime::{AutomationEvent, NavigationFrameEventKind}; use crate::domains::activity::{ProtocolOutputPayloads, ProtocolOutputProjectionContext}; use crate::domains::input::{InputPreparedOutputSlot, InputPreparedOutputs}; @@ -2750,8 +2683,8 @@ mod producer_tests { predecessor, ); assert_eq!( - conn.apply_renderer_document_title_for_session_owner( - Some("SID-title-source"), + conn.apply_renderer_document_title_for_owner( + &CommandOwnerScope::for_session("SID-title-source"), &RendererDocumentTitleChanged { source_document: predecessor, title: "predecessor".to_owned(), @@ -2768,8 +2701,8 @@ mod producer_tests { replacement, ); assert_eq!( - conn.apply_renderer_document_title_for_session_owner( - Some("SID-title-source"), + conn.apply_renderer_document_title_for_owner( + &CommandOwnerScope::for_session("SID-title-source"), &RendererDocumentTitleChanged { source_document: replacement, title: "replacement".to_owned(), @@ -2779,8 +2712,8 @@ mod producer_tests { ); assert_eq!( - conn.apply_renderer_document_title_for_session_owner( - Some("SID-title-source"), + conn.apply_renderer_document_title_for_owner( + &CommandOwnerScope::for_session("SID-title-source"), &RendererDocumentTitleChanged { source_document: predecessor, title: "late predecessor".to_owned(), @@ -2827,7 +2760,6 @@ mod producer_tests { super::emit_javascript_dialog_activity_background_events_async( &mut conn, &mut out, - Some("SID-1"), Some(&mut prepared), ) .await; @@ -2892,7 +2824,6 @@ mod producer_tests { super::emit_javascript_dialog_activity_background_events_async( &mut conn, &mut out, - Some("SID-primary"), Some(&mut prepared), ) .await; @@ -2960,7 +2891,6 @@ mod producer_tests { super::emit_javascript_dialog_activity_background_events_async( &mut conn, &mut out, - Some("SID-primary"), Some(&mut prepared), ) .await; @@ -3009,7 +2939,6 @@ mod producer_tests { super::emit_javascript_dialog_activity_background_events_async( &mut conn, &mut out, - Some("SID-primary"), Some(&mut dialog_output), ) .await; @@ -3044,7 +2973,6 @@ mod producer_tests { super::emit_popup_activity_background_events_async( &mut conn, &mut out, - Some("SID-primary"), Some(&mut popup_output), ) .await; @@ -3117,7 +3045,6 @@ mod producer_tests { super::emit_javascript_dialog_activity_background_events_async( &mut conn, &mut out, - Some("SID-opener"), Some(&mut prepared), ) .await; @@ -3129,7 +3056,6 @@ mod producer_tests { super::emit_popup_activity_background_events_async( &mut conn, &mut out, - Some("SID-opener"), Some(&mut prepared), ) .await; @@ -3197,7 +3123,6 @@ mod producer_tests { super::emit_javascript_dialog_activity_background_events_async( &mut conn, &mut later_out, - Some("SID-opener"), Some(&mut later_dialog), ) .await; @@ -3273,14 +3198,12 @@ mod producer_tests { super::emit_javascript_dialog_activity_background_events_async( &mut conn, &mut out, - Some("SID-opener-no-session"), Some(&mut prepared), ) .await; super::emit_popup_activity_background_events_async( &mut conn, &mut out, - Some("SID-opener-no-session"), Some(&mut prepared), ) .await; @@ -3381,7 +3304,6 @@ mod producer_tests { super::emit_javascript_dialog_activity_background_events_async( &mut conn, &mut out, - Some("SID-dialog-stale-page"), Some(&mut prepared), ) .await; @@ -3440,7 +3362,6 @@ mod producer_tests { super::emit_javascript_dialog_activity_background_events_async( &mut conn, &mut out, - Some("SID-dialog-generation"), Some(&mut prepared), ) .await; @@ -3492,7 +3413,6 @@ mod producer_tests { super::emit_javascript_dialog_activity_background_events_async( &mut conn, &mut out, - Some("SID-dialog-source"), Some(&mut prepared), ) .await; @@ -4810,7 +4730,6 @@ mod producer_tests { super::emit_popup_activity_background_events_async( &mut conn, &mut out, - Some("SID-1"), Some(&mut prepared), ) .await; @@ -4894,7 +4813,6 @@ mod producer_tests { super::emit_popup_activity_background_events_async( &mut conn, &mut out, - Some("SID-opener"), Some(&mut prepared), ) .await; @@ -4961,7 +4879,7 @@ mod producer_tests { super::emit_same_document_navigation_activity_background_events_async( &mut conn, &mut out, - Some("SID-1"), + &CommandOwnerScope::for_session("SID-1"), Some(&mut prepared), ) .await; @@ -5049,7 +4967,7 @@ mod producer_tests { super::emit_same_document_navigation_activity_background_events_async( &mut conn, &mut out, - Some("SID-document-open-same-document"), + &CommandOwnerScope::for_session("SID-document-open-same-document"), Some(&mut prepared), ) .await; @@ -5101,7 +5019,7 @@ mod producer_tests { super::emit_same_document_navigation_activity_background_events_async( &mut conn, &mut out, - Some("SID-stale-page-same-document"), + &CommandOwnerScope::for_session("SID-stale-page-same-document"), Some(&mut prepared), ) .await; @@ -5142,7 +5060,7 @@ mod producer_tests { super::publish_prepared_top_level_location_navigation_owner_action( &mut conn, - Some("SID-location"), + &CommandOwnerScope::for_session("SID-location"), Some(&mut prepared), ); @@ -5228,7 +5146,7 @@ mod producer_tests { )); super::publish_prepared_top_level_location_navigation_owner_action( &mut conn, - Some("SID-document-open-location"), + &CommandOwnerScope::for_session("SID-document-open-location"), Some(&mut prepared), ); let work = take_top_level_location_navigation_work_for_test(&mut conn); @@ -5288,7 +5206,7 @@ mod producer_tests { )); super::publish_prepared_top_level_location_navigation_owner_action( &mut conn, - Some("SID-stale-page-location"), + &CommandOwnerScope::for_session("SID-stale-page-location"), Some(&mut prepared), ); let work = take_top_level_location_navigation_work_for_test(&mut conn); @@ -5843,13 +5761,12 @@ fn current_viewport_surface( ) } -fn current_viewport_surface_for_route( +fn current_viewport_surface_for_owner( conn: &CdpConnection, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> EmulatedViewportSurface { EmulatedViewportSurface::from_metrics( - conn.target_session_owner_emulated_device_metrics_for_route(session_id, owner_route) + conn.target_session_owner_emulated_device_metrics_for_owner(owner) .as_ref(), ) } @@ -5858,33 +5775,19 @@ async fn execute_devtools_get_layout_metrics_command( conn: &mut CdpConnection, command: DevToolsGetLayoutMetricsCommand, ) -> Result { - let mut command = command; - let route = if let Some(target_id) = command.context.target_id.as_ref() { - Some(page_route_for_context_id(conn, target_id.as_str())?) - } else { - None - }; - if route.is_some() { - command.context.session_id = None; - } - let result = - execute_devtools_get_layout_metrics_for_current_owner(conn, command, route.as_ref()).await; + let owner = page_command_owner(conn, &command.context)?; + let result = execute_devtools_get_layout_metrics_for_current_owner(conn, &owner).await; result.map(DevToolsCommandResult::LayoutMetrics) } async fn execute_devtools_get_layout_metrics_for_current_owner( conn: &mut CdpConnection, - command: DevToolsGetLayoutMetricsCommand, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Result { - let session_id = command.context.session_id.as_ref().map(|id| id.as_str()); - let fallback = layout_metrics_result_from_surface(current_viewport_surface_for_route( - conn, - session_id, - owner_route, - )); + let fallback = + layout_metrics_result_from_surface(current_viewport_surface_for_owner(conn, owner)); let Some(page) = conn - .runtime_session_owner_slot_mut_for_route(session_id, owner_route) + .runtime_session_owner_slot_mut_for_owner(owner) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -5897,7 +5800,7 @@ async fn execute_devtools_get_layout_metrics_for_current_owner( devtools_layout_metrics_error(format!("Failed to produce layout metrics: {error}")) })?; let Some(page) = conn - .runtime_session_owner_slot_mut_for_route(session_id, owner_route) + .runtime_session_owner_slot_mut_for_owner(owner) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -6185,7 +6088,7 @@ fn devtools_browsing_context_target_infos(conn: &CdpConnection) -> Vec Result { let target_info = command .context @@ -6202,17 +6105,9 @@ async fn execute_devtools_get_frame_tree_command_async( ) .map(DevToolsCommandResult::GetFrameTree); } - let route = if let Some(target_id) = command.context.target_id.as_ref() { - let route = conn - .target_session_route_for_target_id(target_id.as_str()) - .ok_or_else(|| DevToolsError::new(DevToolsErrorKind::NoSuchTarget, "NoSuchTarget"))?; - command.context.session_id = None; - Some(route) - } else { - None - }; + let owner = page_command_owner(conn, &command.context)?; let max_depth = command.max_depth; - execute_devtools_get_frame_tree_command_for_current_owner_async(conn, command, route) + devtools_frame_tree_for_current_owner_async(conn, command, &owner) .await .map(|frame_tree| { DevToolsCommandResult::GetFrameTree(DevToolsGetFrameTreeResult { @@ -6245,34 +6140,21 @@ fn devtools_service_worker_frame_tree_result( }) } -async fn execute_devtools_get_frame_tree_command_for_current_owner_async( - conn: &mut CdpConnection, - command: DevToolsGetFrameTreeCommand, - route: Option, -) -> Result { - devtools_frame_tree_for_current_owner_async(conn, command, route.as_ref()).await -} - async fn devtools_frame_tree_for_current_owner_async( conn: &mut CdpConnection, command: DevToolsGetFrameTreeCommand, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Result { let command_session_id = command.context.session_id.as_ref().map(|id| id.as_str()); if command_session_id.is_none() && conn.browser_context.is_none() { return Err(devtools_frame_tree_error("BrowserContextNotLoaded")); } let (target_id, target_url, target_security_origin, target_secure_context_type) = conn - .target_session_owner_frame_tree_identity_for_route(command_session_id, owner_route) + .target_session_owner_frame_tree_identity_for_owner(owner) .ok_or_else(|| devtools_frame_tree_error("TargetNotLoaded"))?; - let target_unreachable_url = - network_error_page_unreachable_url(conn, command_session_id, owner_route, &target_url); - let target_loader_id = - frame_tree_loader_id_for_current_owner(conn, command_session_id, owner_route); - if conn - .ensure_document_accessible_for_route(command_session_id, owner_route) - .is_err() - { + let target_unreachable_url = network_error_page_unreachable_url(conn, owner, &target_url); + let target_loader_id = frame_tree_loader_id_for_current_owner(conn, owner); + if conn.ensure_document_accessible_for_owner(owner).is_err() { return Ok(frame_tree_payload( target_id, target_loader_id, @@ -6285,7 +6167,7 @@ async fn devtools_frame_tree_for_current_owner_async( )); } let Some(page) = conn - .runtime_session_owner_slot_mut_for_route(command_session_id, owner_route) + .runtime_session_owner_slot_mut_for_owner(owner) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -6307,10 +6189,7 @@ async fn devtools_frame_tree_for_current_owner_async( let completed = pending.wait().await.map_err(|error| { devtools_frame_tree_error(format!("Failed to snapshot child frame tree: {error}")) })?; - if conn - .ensure_document_accessible_for_route(command_session_id, owner_route) - .is_err() - { + if conn.ensure_document_accessible_for_owner(owner).is_err() { return Ok(frame_tree_payload( target_id, target_loader_id, @@ -6323,7 +6202,7 @@ async fn devtools_frame_tree_for_current_owner_async( )); } let Some(page) = conn - .runtime_session_owner_slot_mut_for_route(command_session_id, owner_route) + .runtime_session_owner_slot_mut_for_owner(owner) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -6361,12 +6240,11 @@ fn default_document_mime_type() -> String { fn network_error_page_unreachable_url( conn: &CdpConnection, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, document_url: &str, ) -> Option { (document_url == NETWORK_ERROR_PAGE_URL) - .then(|| conn.runtime_session_owner_target_url_for_route(session_id, owner_route)) + .then(|| conn.runtime_session_owner_target_url_for_owner(owner)) .flatten() } @@ -6387,10 +6265,9 @@ fn devtools_frame_tree_error(message: impl Into) -> DevToolsError { /// instead claim that the frame belongs to an unrelated document/navigation. fn frame_tree_loader_id_for_current_owner( conn: &CdpConnection, - session_id: Option<&str>, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> String { - conn.target_session_owner_frame_tree_loader_id_for_route(session_id, owner_route) + conn.target_session_owner_frame_tree_loader_id_for_owner(owner) .unwrap_or_default() } @@ -6414,16 +6291,8 @@ fn execute_devtools_get_javascript_dialog_command( conn: &mut CdpConnection, command: DevToolsGetJavaScriptDialogCommand, ) -> Result { - let mut command = command; - let route = if let Some(target_id) = command.context.target_id.as_ref() { - Some(page_route_for_context_id(conn, target_id.as_str())?) - } else { - None - }; - if route.is_some() { - command.context.session_id = None; - } - let result = finish_devtools_get_javascript_dialog_command(conn, command, route.as_ref()); + let owner = page_command_owner(conn, &command.context)?; + let result = finish_devtools_get_javascript_dialog_command(conn, &owner); result.map(DevToolsCommandResult::JavaScriptDialog) } @@ -6431,16 +6300,8 @@ fn execute_devtools_set_javascript_dialog_prompt_text_command( conn: &mut CdpConnection, command: DevToolsSetJavaScriptDialogPromptTextCommand, ) -> Result { - let mut command = command; - let route = if let Some(target_id) = command.context.target_id.as_ref() { - Some(page_route_for_context_id(conn, target_id.as_str())?) - } else { - None - }; - if route.is_some() { - command.context.session_id = None; - } - finish_devtools_set_javascript_dialog_prompt_text_command(conn, command, route.as_ref()) + let owner = page_command_owner(conn, &command.context)?; + finish_devtools_set_javascript_dialog_prompt_text_command(conn, command, &owner) } fn execute_devtools_handle_javascript_dialog_command( @@ -6450,19 +6311,11 @@ fn execute_devtools_handle_javascript_dialog_command( Result, Vec, ) { - let mut command = command; - let route = if let Some(target_id) = command.context.target_id.as_ref() { - Some(match page_route_for_context_id(conn, target_id.as_str()) { - Ok(route) => route, - Err(error) => return (Err(error), Vec::new()), - }) - } else { - None + let owner = match page_command_owner(conn, &command.context) { + Ok(owner) => owner, + Err(error) => return (Err(error), Vec::new()), }; - if route.is_some() { - command.context.session_id = None; - } - let result = finish_devtools_handle_javascript_dialog_command(conn, command, route.as_ref()); + let result = finish_devtools_handle_javascript_dialog_command(conn, command, &owner); match result { Ok(event) => (Ok(DevToolsCommandResult::Empty), vec![event]), Err(error) => (Err(error), Vec::new()), @@ -6503,6 +6356,20 @@ fn page_route_for_context_id( .ok_or_else(|| DevToolsError::new(DevToolsErrorKind::NoSuchTarget, "NoSuchTarget")) } +fn page_command_owner( + conn: &CdpConnection, + context: &DevToolsCommandContext, +) -> Result { + conn.command_owner_scope_for_devtools_context(context) + .ok_or_else(|| { + if context.target_id.is_some() { + DevToolsError::new(DevToolsErrorKind::NoSuchTarget, "NoSuchTarget") + } else { + devtools_frame_tree_error("TargetNotLoaded") + } + }) +} + fn try_start_page_enable_command( conn: &mut CdpConnection, cmd: &Cmd<'_>, @@ -6687,20 +6554,30 @@ fn start_devtools_page_command( DevToolsCommand::GetLayoutMetrics(command) => { start_devtools_get_layout_metrics_command(conn, command_id, command) } - DevToolsCommand::GetJavaScriptDialog(command) => PageCommandTaskStep::Complete( - match finish_devtools_get_javascript_dialog_command(conn, command, None) { - Ok(result) => CommandOutputPlan::from_devtools_result( - DevToolsCommandResult::JavaScriptDialog(result), - ), + DevToolsCommand::GetJavaScriptDialog(command) => { + let owner = page_command_owner(conn, &command.context); + PageCommandTaskStep::Complete(match owner { + Ok(owner) => match finish_devtools_get_javascript_dialog_command(conn, &owner) { + Ok(result) => CommandOutputPlan::from_devtools_result( + DevToolsCommandResult::JavaScriptDialog(result), + ), + Err(error) => CommandOutputPlan::from_devtools_error(error), + }, Err(error) => CommandOutputPlan::from_devtools_error(error), - }, - ), - DevToolsCommand::SetJavaScriptDialogPromptText(command) => PageCommandTaskStep::Complete( - match finish_devtools_set_javascript_dialog_prompt_text_command(conn, command, None) { - Ok(result) => CommandOutputPlan::from_devtools_result(result), + }) + } + DevToolsCommand::SetJavaScriptDialogPromptText(command) => { + let owner = page_command_owner(conn, &command.context); + PageCommandTaskStep::Complete(match owner { + Ok(owner) => match finish_devtools_set_javascript_dialog_prompt_text_command( + conn, command, &owner, + ) { + Ok(result) => CommandOutputPlan::from_devtools_result(result), + Err(error) => CommandOutputPlan::from_devtools_error(error), + }, Err(error) => CommandOutputPlan::from_devtools_error(error), - }, - ), + }) + } DevToolsCommand::HandleJavaScriptDialog(command) => PageCommandTaskStep::Complete( complete_devtools_handle_javascript_dialog_command(conn, command), ), @@ -6893,8 +6770,9 @@ fn start_devtools_get_frame_tree_command( "BrowserContextNotLoaded", )); }; + let owner = CommandOwnerScope::capture(conn, command_session_id); let (target_id, target_url, target_security_origin, target_secure_context_type) = - match conn.target_session_owner_frame_tree_identity(command_session_id) { + match conn.target_session_owner_frame_tree_identity_for_owner(&owner) { Some(identity) => identity, None => { return PageCommandTaskStep::Complete(CommandOutputPlan::error( @@ -6903,13 +6781,9 @@ fn start_devtools_get_frame_tree_command( )); } }; - let target_unreachable_url = - network_error_page_unreachable_url(conn, command_session_id, None, &target_url); - let target_loader_id = frame_tree_loader_id_for_current_owner(conn, command_session_id, None); - if conn - .ensure_document_accessible_for_session_owner(command_session_id) - .is_err() - { + let target_unreachable_url = network_error_page_unreachable_url(conn, &owner, &target_url); + let target_loader_id = frame_tree_loader_id_for_current_owner(conn, &owner); + if conn.ensure_document_accessible_for_owner(&owner).is_err() { return PageCommandTaskStep::Complete(get_frame_tree_command_output_plan( output_kind, target_id, @@ -6924,7 +6798,7 @@ fn start_devtools_get_frame_tree_command( )); } let Some(page) = conn - .runtime_session_owner_slot_mut(command_session_id) + .runtime_session_owner_slot_mut_for_owner(&owner) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -7496,8 +7370,6 @@ pub(crate) async fn complete_pending_page_command( ) -> PageCommandTaskStep { let command_id = completed.command_id; let owner_scope = completed.owner_scope.clone(); - let session_id = completed.owner_scope.session_id().map(str::to_owned); - let owner_route = completed.owner_scope.session_owner_route().cloned(); if let Some(predecessor) = completed.kind.renderer_output_predecessor() { command_context.set_renderer_output_predecessor(predecessor); } @@ -7533,10 +7405,7 @@ pub(crate) async fn complete_pending_page_command( }; let completed_script = { let Some(page) = conn - .runtime_session_owner_slot_mut_for_route( - session_id.as_deref(), - owner_route.as_ref(), - ) + .runtime_session_owner_slot_mut_for_owner(&owner_scope) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -7569,10 +7438,7 @@ pub(crate) async fn complete_pending_page_command( } }; let Some(page) = conn - .runtime_session_owner_slot_mut_for_route( - session_id.as_deref(), - owner_route.as_ref(), - ) + .runtime_session_owner_slot_mut_for_owner(&owner_scope) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -7635,10 +7501,7 @@ pub(crate) async fn complete_pending_page_command( } }; let Some(page) = conn - .runtime_session_owner_slot_mut_for_route( - session_id.as_deref(), - owner_route.as_ref(), - ) + .runtime_session_owner_slot_mut_for_owner(&owner_scope) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -7666,10 +7529,7 @@ pub(crate) async fn complete_pending_page_command( }; let (result, output) = { let Some(page) = conn - .runtime_session_owner_slot_mut_for_route( - session_id.as_deref(), - owner_route.as_ref(), - ) + .runtime_session_owner_slot_mut_for_owner(&owner_scope) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -7722,7 +7582,7 @@ pub(crate) async fn complete_pending_page_command( completed, } => { if conn - .ensure_document_accessible_for_route(session_id.as_deref(), owner_route.as_ref()) + .ensure_document_accessible_for_owner(&owner_scope) .is_err() { return PageCommandTaskStep::Complete(get_frame_tree_command_output_plan( @@ -7739,10 +7599,7 @@ pub(crate) async fn complete_pending_page_command( )); } let Some(page) = conn - .runtime_session_owner_slot_mut_for_route( - session_id.as_deref(), - owner_route.as_ref(), - ) + .runtime_session_owner_slot_mut_for_owner(&owner_scope) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -7800,10 +7657,7 @@ pub(crate) async fn complete_pending_page_command( } }; let Some(page) = conn - .runtime_session_owner_slot_mut_for_route( - session_id.as_deref(), - owner_route.as_ref(), - ) + .runtime_session_owner_slot_mut_for_owner(&owner_scope) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -7834,10 +7688,7 @@ pub(crate) async fn complete_pending_page_command( )); } }; - let page = match conn.loaded_page_mut_for_protocol_access_for_route( - session_id.as_deref(), - owner_route.as_ref(), - ) { + let page = match conn.loaded_page_mut_for_protocol_access_for_owner(&owner_scope) { Ok(page) => page, Err(message) => { return PageCommandTaskStep::Complete(CommandOutputPlan::error( @@ -7867,10 +7718,7 @@ pub(crate) async fn complete_pending_page_command( )); } }; - let page = match conn.loaded_page_mut_for_protocol_access_for_route( - session_id.as_deref(), - owner_route.as_ref(), - ) { + let page = match conn.loaded_page_mut_for_protocol_access_for_owner(&owner_scope) { Ok(page) => page, Err(message) => { return PageCommandTaskStep::Complete(CommandOutputPlan::error( @@ -7915,10 +7763,7 @@ pub(crate) async fn complete_pending_page_command( )); } }; - let page = match conn.loaded_page_mut_for_protocol_access_for_route( - session_id.as_deref(), - owner_route.as_ref(), - ) { + let page = match conn.loaded_page_mut_for_protocol_access_for_owner(&owner_scope) { Ok(page) => page, Err(message) => { return PageCommandTaskStep::Complete(CommandOutputPlan::error( @@ -7974,9 +7819,8 @@ pub(crate) async fn complete_pending_page_command( })) } DevToolsPrintToPdfTransferMode::ReturnAsStream => { - let stream = match conn.open_io_stream_body_source_for_route( - session_id.as_deref(), - owner_route.as_ref(), + let stream = match conn.open_io_stream_body_source_for_owner( + &owner_scope, CapturedBody::from_bytes_spooled(pdf), ) { Ok(stream) => stream, diff --git a/moli-protocol/src/domains/page/app_manifest.rs b/moli-protocol/src/domains/page/app_manifest.rs index 86e6372e9a..233d368399 100644 --- a/moli-protocol/src/domains/page/app_manifest.rs +++ b/moli-protocol/src/domains/page/app_manifest.rs @@ -128,8 +128,6 @@ pub(super) fn complete_get_app_manifest_command( completed: CompletedGetAppManifestCommand, command_context: &mut CommandDispatchContext, ) -> PageCommandTaskStep { - let session_id = owner.session_id(); - let owner_route = owner.session_owner_route(); match completed.work { CompletedGetAppManifestWork::Prepare(completion) => { let completion = match completion { @@ -142,7 +140,7 @@ pub(super) fn complete_get_app_manifest_command( } }; let preparation = match conn - .loaded_page_mut_for_protocol_access_for_route(session_id, owner_route) + .loaded_page_mut_for_protocol_access_for_owner(owner) .and_then(|page| { page.finish_prepare_app_manifest_load(completion) .map_err(|error| error.to_string()) @@ -174,15 +172,14 @@ pub(super) fn complete_get_app_manifest_command( } CompletedGetAppManifestWork::Fetch(outcome) => { let (result, publication) = (*outcome).into_parts(); - let pending = - match conn.loaded_page_mut_for_protocol_access_for_route(session_id, owner_route) { - Ok(page) => page.start_publish_app_manifest_load(publication), - Err(message) => { - return PageCommandTaskStep::Complete(CommandOutputPlan::error( - -32000, message, - )); - } - }; + let pending = match conn.loaded_page_mut_for_protocol_access_for_owner(owner) { + Ok(page) => page.start_publish_app_manifest_load(publication), + Err(message) => { + return PageCommandTaskStep::Complete(CommandOutputPlan::error( + -32000, message, + )); + } + }; match pending { Ok(pending) => pending_step( command_id, @@ -212,7 +209,7 @@ pub(super) fn complete_get_app_manifest_command( } }; let output = match conn - .loaded_page_mut_for_protocol_access_for_route(session_id, owner_route) + .loaded_page_mut_for_protocol_access_for_owner(owner) .and_then(|page| { page.finish_publish_app_manifest_load(completion) .map_err(|error| error.to_string()) @@ -226,7 +223,7 @@ pub(super) fn complete_get_app_manifest_command( }; let mut ordered_events = Vec::new(); command_context.consume_renderer_command_turn_output(output); - conn.ingest_runtime_session_owner_output_updates_for_route(session_id, owner_route); + conn.ingest_runtime_session_owner_output_updates_for_owner(owner); emit_pending_network_backlog_activity_background_events( conn, &mut ordered_events, diff --git a/moli-protocol/src/domains/page/lifecycle.rs b/moli-protocol/src/domains/page/lifecycle.rs index a025da2ab7..dde75b4a85 100644 --- a/moli-protocol/src/domains/page/lifecycle.rs +++ b/moli-protocol/src/domains/page/lifecycle.rs @@ -185,8 +185,7 @@ pub(crate) fn emit_bound_renderer_document_lifecycle_background_events( binding: &CommittedRendererDocumentBinding, events: &[RendererDocumentLifecycleEvent], ) { - let session_ids = - conn.page_event_session_ids_for_route(owner.session_id(), owner.session_owner_route()); + let session_ids = conn.page_event_session_ids_for_owner(owner); for event in events { if event.frame != binding.renderer_frame || event.document != binding.renderer_document { continue; @@ -197,15 +196,11 @@ pub(crate) fn emit_bound_renderer_document_lifecycle_background_events( RendererDocumentLifecycleMilestone::DomContentLoaded, ) => { for session_id in &session_ids { - let owner_route = session_id - .is_none() - .then_some(owner.session_owner_route()) - .flatten(); - if crate::domains::dom::dom_agent_enabled_for_route( - conn, - session_id.as_deref(), - owner_route, - ) { + let event_owner = session_id + .as_deref() + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); + if crate::domains::dom::dom_agent_enabled_for_owner(conn, &event_owner) { emit_cdp_page_background_automation_event( out, navigation_frame_event( @@ -217,11 +212,8 @@ pub(crate) fn emit_bound_renderer_document_lifecycle_background_events( session_id.as_deref(), ); } - let lifecycle_enabled = page_lifecycle_events_enabled_for_route( - conn, - session_id.as_deref(), - owner_route, - ); + let lifecycle_enabled = + page_lifecycle_events_enabled_for_owner(conn, &event_owner); emit_renderer_navigation_domcontentloaded_background_events( out, session_id.as_deref(), @@ -236,15 +228,12 @@ pub(crate) fn emit_bound_renderer_document_lifecycle_background_events( RendererDocumentLifecycleMilestone::Load, ) => { for session_id in &session_ids { - let owner_route = session_id - .is_none() - .then_some(owner.session_owner_route()) - .flatten(); - let lifecycle_enabled = page_lifecycle_events_enabled_for_route( - conn, - session_id.as_deref(), - owner_route, - ); + let event_owner = session_id + .as_deref() + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); + let lifecycle_enabled = + page_lifecycle_events_enabled_for_owner(conn, &event_owner); emit_renderer_navigation_load_background_events( out, session_id.as_deref(), @@ -263,18 +252,15 @@ pub(crate) fn emit_bound_renderer_document_lifecycle_background_events( | RendererLifecycleStartReason::JavascriptDocumentReplacement, } => { let frame_identity = conn - .target_session_owner_frame_tree_identity_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + .target_session_owner_frame_tree_identity_for_owner(owner) .map(|(_, url, security_origin, secure_context_type)| { (url, security_origin, secure_context_type) }); for session_id in &session_ids { - let owner_route = session_id - .is_none() - .then_some(owner.session_owner_route()) - .flatten(); + let event_owner = session_id + .as_deref() + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); if let Some((url, security_origin, secure_context_type)) = frame_identity.as_ref() { @@ -289,11 +275,8 @@ pub(crate) fn emit_bound_renderer_document_lifecycle_background_events( secure_context_type.clone(), )); } - let lifecycle_enabled = page_lifecycle_events_enabled_for_route( - conn, - session_id.as_deref(), - owner_route, - ); + let lifecycle_enabled = + page_lifecycle_events_enabled_for_owner(conn, &event_owner); emit_navigation_lifecycle_init_background_events( out, session_id.as_deref(), @@ -310,12 +293,11 @@ pub(crate) fn emit_bound_renderer_document_lifecycle_background_events( } } -fn page_lifecycle_events_enabled_for_route( +fn page_lifecycle_events_enabled_for_owner( conn: &CdpConnection, - session_id: Option<&str>, - owner_route: Option<&crate::conn::CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> bool { - conn.target_page_session_state_for_route(session_id, owner_route) + conn.target_page_session_state_for_owner(owner) .is_some_and(|state| state.page_lifecycle_events) } diff --git a/moli-protocol/src/domains/page/main_document_commit.rs b/moli-protocol/src/domains/page/main_document_commit.rs index b44a8a78d6..e2c0162017 100644 --- a/moli-protocol/src/domains/page/main_document_commit.rs +++ b/moli-protocol/src/domains/page/main_document_commit.rs @@ -1,6 +1,6 @@ use moli_core::page::RendererMainDocumentCommit; -use crate::conn::CdpConnection; +use crate::conn::{CdpConnection, CommandOwnerScope}; use crate::domains::activity::{ ProtocolOutputPayloads, ProtocolOutputProjectionContext, ProtocolOutputSink, ProtocolOutputSlot, }; @@ -46,18 +46,14 @@ pub(in crate::domains) async fn project_main_document_commit_async( for commit in commits { let owner = context.owner(); - let Some((current_frame_id, _, _, _)) = conn - .target_session_owner_frame_tree_identity_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + let Some((current_frame_id, _, _, _)) = + conn.target_session_owner_frame_tree_identity_for_owner(owner) else { continue; }; - let Some(current_loader_id) = conn.target_session_owner_frame_tree_loader_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ) else { + let Some(current_loader_id) = + conn.target_session_owner_frame_tree_loader_id_for_owner(owner) + else { continue; }; if current_frame_id != commit.frame_id || current_loader_id != commit.loader_id { @@ -67,16 +63,15 @@ pub(in crate::domains) async fn project_main_document_commit_async( continue; } - let session_ids = - conn.page_event_session_ids_for_route(owner.session_id(), owner.session_owner_route()); + let session_ids = conn.page_event_session_ids_for_owner(owner); let mut events = Vec::new(); for session_id in session_ids { - let event_owner_route = session_id - .is_none() - .then_some(owner.session_owner_route()) - .flatten(); + let event_owner = session_id + .as_deref() + .map(CommandOwnerScope::for_session) + .unwrap_or_else(|| owner.clone()); let lifecycle_enabled = conn - .target_page_session_state_for_route(session_id.as_deref(), event_owner_route) + .target_page_session_state_for_owner(&event_owner) .is_some_and(|state| state.page_lifecycle_events); super::emit_navigation_lifecycle_init_background_events( &mut events, @@ -87,11 +82,7 @@ pub(in crate::domains) async fn project_main_document_commit_async( commit.timestamp, ); - let dom_enabled = crate::domains::dom::dom_agent_enabled_for_route( - conn, - session_id.as_deref(), - event_owner_route, - ); + let dom_enabled = crate::domains::dom::dom_agent_enabled_for_owner(conn, &event_owner); super::emit_navigation_frame_commit_background_events( &mut events, session_id.as_deref(), diff --git a/moli-protocol/src/domains/page/navigation.rs b/moli-protocol/src/domains/page/navigation.rs index fa51b11d7e..5cb45e2345 100644 --- a/moli-protocol/src/domains/page/navigation.rs +++ b/moli-protocol/src/domains/page/navigation.rs @@ -354,9 +354,7 @@ fn send_background_navigation_started( url: &str, initiator: NavigationStartInitiator, ) { - for session_id in - conn.page_event_session_ids_for_route(owner.session_id(), owner.session_owner_route()) - { + for session_id in conn.page_event_session_ids_for_owner(owner) { let mut events = Vec::new(); emit_navigation_started_background_events( &mut events, @@ -381,9 +379,7 @@ fn emit_navigation_started_for_session_owner( url: &str, initiator: NavigationStartInitiator, ) { - for session_id in - conn.page_event_session_ids_for_route(owner.session_id(), owner.session_owner_route()) - { + for session_id in conn.page_event_session_ids_for_owner(owner) { emit_navigation_started_background_events( out, session_id.as_deref(), @@ -422,11 +418,7 @@ impl MaterializedNavigationCompletion { } pub(crate) fn is_current_for_connection(&self, conn: &CdpConnection) -> bool { - conn.accepts_pending_document_navigation_for_route( - self.state.owner.session_id(), - self.state.owner.session_owner_route(), - &self.token, - ) + conn.accepts_pending_document_navigation_for_owner(&self.state.owner, &self.token) } pub(crate) fn requested_url(&self) -> &str { @@ -488,11 +480,7 @@ impl BackgroundMainDocumentBodyCompletion { } pub(crate) fn is_current_for_connection(&self, conn: &CdpConnection) -> bool { - conn.accepts_document_body_completion_for_route( - self.state.owner.session_id(), - self.state.owner.session_owner_route(), - &self.token, - ) + conn.accepts_document_body_completion_for_owner(&self.state.owner, &self.token) } pub(crate) fn record_if_current(self, conn: &mut CdpConnection) { @@ -501,9 +489,8 @@ impl BackgroundMainDocumentBodyCompletion { } match self.body { Ok(body) => { - let _ = conn.record_main_document_resource_body_for_route( - self.state.owner.session_id(), - self.state.owner.session_owner_route(), + let _ = conn.record_main_document_resource_body_for_owner( + &self.state.owner, self.state.frame_id.clone(), self.state.loader_id.clone(), self.final_url, @@ -582,11 +569,7 @@ impl BackgroundNavigationLifecycleCompletion { } pub(crate) fn is_current_for_connection(&self, conn: &CdpConnection) -> bool { - conn.accepts_pending_document_navigation_for_route( - self.state.owner.session_id(), - self.state.owner.session_owner_route(), - &self.token, - ) + conn.accepts_pending_document_navigation_for_owner(&self.state.owner, &self.token) } pub(crate) fn requested_url(&self) -> &str { @@ -702,9 +685,9 @@ fn navigation_cookie_access_report_for_owner( // at the destination document. Redirect diagnostics still need the // pre-commit initiator, so callers may override it with a snapshot taken // before mutating browser context state. - let initiator_url = initiator_url_override.cloned().or_else(|| { - conn.navigation_initiator_url_for_route(owner.session_id(), owner.session_owner_route()) - }); + let initiator_url = initiator_url_override + .cloned() + .or_else(|| conn.navigation_initiator_url_for_owner(owner)); let request_context = network::navigation_cookie_request_context( request_url, method, @@ -968,8 +951,8 @@ pub(crate) fn execute_devtools_get_navigation_history_command( let route = conn .target_session_route_for_target_id(target_id.as_str()) .ok_or_else(|| DevToolsError::new(DevToolsErrorKind::NoSuchTarget, "NoSuchTarget"))?; - let snapshot = - conn.target_session_owner_navigation_history_snapshot_for_route(None, Some(&route)); + let owner = CommandOwnerScope::for_route(route); + let snapshot = conn.target_session_owner_navigation_history_snapshot_for_owner(&owner); let Some((current_index, entries)) = snapshot else { return Err(DevToolsError::new( DevToolsErrorKind::NoSuchTarget, @@ -1038,20 +1021,22 @@ fn start_protocol_neutral_navigation_command( let wait = devtools_navigation_wait(&command); let result_url = match &command { DevToolsCommand::Navigate(command) => command.url.clone(), - DevToolsCommand::Reload(_) => match conn - .runtime_session_owner_target_url_for_route(None, Some(&route)) - { - Some(url) => url, - None => { - let error = DevToolsError::new(DevToolsErrorKind::NoSuchTarget, "TargetNotLoaded"); - return ( - PageCommandTaskStep::Complete(CommandOutputPlan::from_devtools_error( - error.clone(), - )), - Err(error), - ); + DevToolsCommand::Reload(_) => { + let owner = CommandOwnerScope::for_route(route.clone()); + match conn.runtime_session_owner_target_url_for_owner(&owner) { + Some(url) => url, + None => { + let error = + DevToolsError::new(DevToolsErrorKind::NoSuchTarget, "TargetNotLoaded"); + return ( + PageCommandTaskStep::Complete(CommandOutputPlan::from_devtools_error( + error.clone(), + )), + Err(error), + ); + } } - }, + } DevToolsCommand::TraverseHistory(_) => String::new(), _ => String::new(), }; @@ -1296,11 +1281,8 @@ fn direct_navigation_result_from_completed_load( completed: &CompletedNavigateLoadCommand, result: &mut DirectNavigationResult, ) -> Result<(), DevToolsError> { - if !conn.accepts_pending_document_navigation_for_route( - completed.state.owner.session_id(), - completed.state.owner.session_owner_route(), - &completed.token, - ) { + if !conn.accepts_pending_document_navigation_for_owner(&completed.state.owner, &completed.token) + { if superseded_cdp_page_navigate_payload(&completed.state).is_some() { result.set_cdp_navigation_aborted(&completed.state.frame_id); return Ok(()); @@ -1400,7 +1382,8 @@ fn fill_navigation_id_from_current_loader_for_route( if result.navigation_id.is_some() { return; } - let loader_id = conn.current_document_loader_id_for_route(None, Some(route)); + let owner = CommandOwnerScope::for_route(route.clone()); + let loader_id = conn.current_document_loader_id_for_owner(&owner); result.ensure_navigation_id_from_loader(loader_id); } @@ -1449,10 +1432,7 @@ fn session_owner_navigation_is_same_document_fragment( owner: &CommandOwnerScope, target: &str, ) -> bool { - let Some(current) = conn.runtime_session_owner_target_url_for_route( - owner.session_id(), - owner.session_owner_route(), - ) else { + let Some(current) = conn.runtime_session_owner_target_url_for_owner(owner) else { return false; }; let (Ok(mut current), Ok(mut target)) = (Url::parse(¤t), Url::parse(target)) else { @@ -1494,7 +1474,7 @@ fn start_top_level_same_document_navigate( result_payload: Value, ) -> NavigateCommandStart { let Some(page) = conn - .runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) + .runtime_session_owner_slot_mut_for_owner(owner) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -1537,27 +1517,23 @@ fn start_child_frame_navigate_command( wait: DevToolsNavigationWait, result_payload: Value, ) -> NavigateCommandStart { - let Some(source_document) = conn.target_root_document_lifecycle_identity_for_route( - owner.session_id(), - owner.session_owner_route(), - ) else { + let Some(source_document) = conn.target_root_document_lifecycle_identity_for_owner(owner) + else { return NavigateCommandStart::CompletePlan(CommandOutputPlan::error( -32000, "NoDocumentLoaded", )); }; - let Some(activity_binding) = conn.target_root_document_protocol_attachment_identity_for_route( - owner.session_id(), - owner.session_owner_route(), - source_document, - ) else { + let Some(activity_binding) = + conn.target_root_document_protocol_attachment_identity_for_owner(owner, source_document) + else { return NavigateCommandStart::CompletePlan(CommandOutputPlan::error( -32000, "NoDocumentLoaded", )); }; let Some(page) = conn - .runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) + .runtime_session_owner_slot_mut_for_owner(owner) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -1641,29 +1617,15 @@ fn build_cdp_reload_command( fn start_devtools_reload_command( conn: &mut CdpConnection, command_id: Option, - command: &DevToolsReloadCommand, + _command: &DevToolsReloadCommand, options: DevToolsNavigationStartOptions, ) -> PageCommandTaskStep { - let context_session_id = command.context.session_id.as_ref().map(|id| id.as_str()); - let owner = if options.owner.session_id().is_none() - && options.owner.session_owner_route().is_none() - && context_session_id.is_some() - { - CommandOwnerScope::capture(conn, context_session_id) - } else { - options.owner - }; - let Some(url) = conn.runtime_session_owner_target_url_for_route( - owner.session_id(), - owner.session_owner_route(), - ) else { + let owner = options.owner; + let Some(url) = conn.runtime_session_owner_target_url_for_owner(&owner) else { return PageCommandTaskStep::Complete(CommandOutputPlan::error(-31998, "TargetNotLoaded")); }; if conn - .mark_next_navigation_history_replace_current_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + .mark_next_navigation_history_replace_current_for_owner(&owner) .is_none() { return PageCommandTaskStep::Complete(CommandOutputPlan::error(-31998, "TargetNotLoaded")); @@ -1757,11 +1719,8 @@ fn resolve_devtools_history_traversal_destination( owner: &CommandOwnerScope, destination: &DevToolsHistoryTraversalDestination, ) -> Result { - let Some((current_index, entries)) = conn - .target_session_owner_navigation_history_snapshot_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + let Some((current_index, entries)) = + conn.target_session_owner_navigation_history_snapshot_for_owner(owner) else { return Err(DevToolsError::new( DevToolsErrorKind::NoSuchTarget, @@ -1823,10 +1782,7 @@ fn start_same_document_history_traversal_command( fallback: HistoryTraversalUrlFallback, ) -> PageCommandTaskStep { let page = conn - .runtime_session_owner_slot_mut_for_route( - fallback.owner.session_id(), - fallback.owner.session_owner_route(), - ) + .runtime_session_owner_slot_mut_for_owner(&fallback.owner) .ok() .and_then(|slot| slot.loaded_page()) .ok_or_else(|| anyhow::anyhow!("TargetNotLoaded")); @@ -1873,10 +1829,7 @@ pub(super) fn complete_pending_same_document_history_traversal_command( } }; let result = conn - .runtime_session_owner_slot_mut_for_route( - fallback.owner.session_id(), - fallback.owner.session_owner_route(), - ) + .runtime_session_owner_slot_mut_for_owner(&fallback.owner) .ok() .and_then(|slot| slot.loaded_page_mut()) .ok_or_else(|| anyhow::anyhow!("TargetNotLoaded")) @@ -1922,21 +1875,20 @@ fn start_history_traversal_url_fallback( pub(super) fn start_session_owner_history_traversal_from_renderer( conn: &mut CdpConnection, - session_id: Option<&str>, + owner: &CommandOwnerScope, delta: i64, ) -> PageCommandTaskStep { - let owner = CommandOwnerScope::capture(conn, session_id); - let reloaded_after_crash_session_ids = reloaded_after_crash_session_ids(conn, &owner); + let reloaded_after_crash_session_ids = reloaded_after_crash_session_ids(conn, owner); let destination = DevToolsHistoryTraversalDestination::Delta(delta); let (entry_id, url) = - match resolve_devtools_history_traversal_destination(conn, &owner, &destination) { + match resolve_devtools_history_traversal_destination(conn, owner, &destination) { Ok(ResolvedDevToolsHistoryTraversal::Entry { entry_id, url, .. }) => (entry_id, url), Ok(ResolvedDevToolsHistoryTraversal::Noop) => { return PageCommandTaskStep::Complete(CommandOutputPlan::success()); } Err(error) => { tracing::debug!( - session_id, + session_id = owner.session_id(), delta, error = error.message.as_str(), "ignoring renderer history traversal without a browser-side destination" @@ -1950,7 +1902,7 @@ pub(super) fn start_session_owner_history_traversal_from_renderer( entry_id, &url, DevToolsNavigationStartOptions { - owner, + owner: owner.clone(), result_projection: NavigationResultProjection::Cdp(json!({})), reloaded_after_crash_session_ids, allow_background_navigation: false, @@ -1974,11 +1926,7 @@ fn start_resolved_history_traversal_command( source: HistoryTraversalStartSource, ) -> PageCommandTaskStep { if conn - .mark_next_navigation_history_traverse_to_entry_for_route( - options.owner.session_id(), - options.owner.session_owner_route(), - entry_id, - ) + .mark_next_navigation_history_traverse_to_entry_for_owner(&options.owner, entry_id) .is_none() { return PageCommandTaskStep::Complete(CommandOutputPlan::error(-31998, "TargetNotLoaded")); @@ -2017,15 +1965,8 @@ fn start_devtools_traverse_history_command( conn: &mut CdpConnection, command_id: Option, command: &DevToolsTraverseHistoryCommand, - mut options: DevToolsNavigationStartOptions, + options: DevToolsNavigationStartOptions, ) -> PageCommandTaskStep { - let context_session_id = command.context.session_id.as_ref().map(|id| id.as_str()); - if options.owner.session_id().is_none() - && options.owner.session_owner_route().is_none() - && context_session_id.is_some() - { - options.owner = CommandOwnerScope::capture(conn, context_session_id); - } let (entry_id, url, same_document_delta) = match resolve_devtools_history_traversal_destination( conn, &options.owner, @@ -2600,7 +2541,7 @@ pub(super) fn complete_reset_navigation_history_command( } }; let Some(page) = conn - .runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) + .runtime_session_owner_slot_mut_for_owner(owner) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -2621,7 +2562,7 @@ pub(super) fn complete_reset_navigation_history_command( )); } } - match conn.reset_navigation_history_for_route(owner.session_id(), owner.session_owner_route()) { + match conn.reset_navigation_history_for_owner(owner) { Some(true) => PageCommandTaskStep::Complete(CommandOutputPlan::success()), Some(false) => PageCommandTaskStep::Complete(CommandOutputPlan::error( -32000, @@ -2636,12 +2577,12 @@ fn reloaded_after_crash_session_ids( owner: &CommandOwnerScope, ) -> Vec> { if !conn - .target_owner_state_for_route(owner.session_id(), owner.session_owner_route()) + .target_owner_state_for_owner(owner) .is_some_and(|owner_state| owner_state.target_crash_state.is_crashed()) { return Vec::new(); } - conn.page_event_session_ids_for_route(owner.session_id(), owner.session_owner_route()) + conn.page_event_session_ids_for_owner(owner) .into_iter() .filter(|event_session_id| { conn.target_runtime_session_state_for_session(event_session_id.as_deref()) @@ -2656,13 +2597,9 @@ fn clear_crash_state_after_navigation( owner: &CommandOwnerScope, reloaded_after_crash_session_ids: &[Option], ) { - let _ = conn.with_target_owner_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |owner_state| { - owner_state.target_crash_state.clear(); - }, - ); + let _ = conn.with_target_owner_state_for_owner_mut(owner, |owner_state| { + owner_state.target_crash_state.clear(); + }); for session_id in reloaded_after_crash_session_ids { out.push(inspector_target_reloaded_after_crash_event( session_id.as_deref(), @@ -2676,13 +2613,9 @@ fn clear_crash_state_after_navigation_into_plan( owner: &CommandOwnerScope, reloaded_after_crash_session_ids: &[Option], ) { - let _ = conn.with_target_owner_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |owner_state| { - owner_state.target_crash_state.clear(); - }, - ); + let _ = conn.with_target_owner_state_for_owner_mut(owner, |owner_state| { + owner_state.target_crash_state.clear(); + }); for session_id in reloaded_after_crash_session_ids { plan.push_background_event(inspector_target_reloaded_after_crash_event( session_id.as_deref(), @@ -2785,7 +2718,6 @@ fn start_navigate_to_url_command_with_background_policy_and_request( initiator: NavigationStartInitiator, ) -> NavigateCommandStart { let command_session_id = owner.session_id(); - let owner_route = owner.session_owner_route(); let mut out = Vec::new(); let timestamp = monotonic_timestamp_seconds(); let mut fetch_request_stage = FetchRequestStage::Request; @@ -2801,9 +2733,8 @@ fn start_navigate_to_url_command_with_background_policy_and_request( error.to_string(), )); } - let mut navigation_preflight = conn.prepare_navigation_request_for_route( - command_session_id, - owner_route, + let mut navigation_preflight = conn.prepare_navigation_request_for_owner( + owner, &requested_url, referrer, url.starts_with("data:"), @@ -2812,7 +2743,7 @@ fn start_navigate_to_url_command_with_background_policy_and_request( .as_ref() .map(|preflight| preflight.frame_id.clone()) .or_else(|| { - conn.target_owner_identity_for_route(command_session_id, owner_route) + conn.target_owner_identity_for_owner(owner) .and_then(|(_, target_id)| target_id) }) .unwrap_or_else(|| "FRAME-0".to_owned()); @@ -2910,11 +2841,8 @@ fn start_navigate_to_url_command_with_background_policy_and_request( } let navigation_loader_id = navigation_state.loader_id.as_str(); - let document_navigation_token = conn.start_document_navigation_for_route( - command_session_id, - owner_route, - navigation_loader_id.to_owned(), - ); + let document_navigation_token = + conn.start_document_navigation_for_owner(owner, navigation_loader_id.to_owned()); let Some(document_navigation_token) = document_navigation_token else { return NavigateCommandStart::CompletePlan(CommandOutputPlan::error( -31998, @@ -2976,9 +2904,8 @@ fn start_navigate_to_url_command_with_background_policy_and_request( ); } pending.navigation.request_announced = pending.navigation.request_id.is_some(); - let _ = conn.register_pending_fetch_navigation_request_for_route( - pending.navigation.owner.session_id(), - pending.navigation.owner.session_owner_route(), + let _ = conn.register_pending_fetch_navigation_request_for_owner( + &pending.navigation.owner, pending.clone(), ); out.push(fetch::request_paused_background_event( @@ -3016,8 +2943,7 @@ fn start_navigate_to_url_command_with_background_policy_and_request( } if allow_background_navigation - && let Some(sender) = - conn.background_navigation_completion_sender_for_route(command_session_id, owner_route) + && let Some(sender) = conn.background_navigation_completion_sender_for_owner(owner) { let body_progress_source = if navigation_state.request_id.is_some() { let request_cookie_report = navigation_cookie_access_report_for_owner( @@ -3135,10 +3061,7 @@ pub(super) fn start_initial_document_navigation_for_session_owner( owner: &CommandOwnerScope, result_payload: Value, ) -> Result { - let Some(url) = conn.runtime_session_owner_target_url_for_route( - owner.session_id(), - owner.session_owner_route(), - ) else { + let Some(url) = conn.runtime_session_owner_target_url_for_owner(owner) else { if conn.browser_context.is_none() { return Err(CommandOutputPlan::error(-31998, "BrowserContextNotLoaded")); } @@ -3169,11 +3092,7 @@ pub(super) async fn complete_pending_navigate_load_command( engine, navigation, } = completed; - let is_current = conn.accepts_pending_document_navigation_for_route( - state.owner.session_id(), - state.owner.session_owner_route(), - &token, - ); + let is_current = conn.accepts_pending_document_navigation_for_owner(&state.owner, &token); let should_replace_owner_engine = is_current && matches!( navigation, @@ -3222,10 +3141,7 @@ pub(super) async fn complete_pending_child_frame_navigate_command( }; let (navigated, renderer_output) = { let Some(page) = conn - .runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + .runtime_session_owner_slot_mut_for_owner(owner) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -3312,10 +3228,7 @@ pub(super) async fn complete_pending_same_document_navigate_command( }; let (navigated, output) = { let Some(page) = conn - .runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + .runtime_session_owner_slot_mut_for_owner(owner) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -3503,10 +3416,7 @@ async fn complete_materialized_navigation_into_buffer_inner_async( } } let primary_protocol_session_id = conn - .runtime_session_owner_primary_session_id_for_route( - navigation_owner.session_id(), - navigation_owner.session_owner_route(), - ) + .runtime_session_owner_primary_session_id_for_owner(&navigation_owner) .or_else(|| navigation_session_id.clone()); let (routed_renderer_output, renderer_call_replacements) = conn .finish_renderer_document_navigation_for_owner(&navigation_owner, &token) @@ -3567,17 +3477,17 @@ fn push_navigation_commit_error( fn emit_same_document_navigation_background_event( conn: &mut CdpConnection, out: &mut Vec, - session_id: Option<&str>, + owner: &CommandOwnerScope, url: Url, navigation_type: &str, history_update: SameDocumentHistoryUpdate, ) { let Some(frame_id) = - conn.record_same_document_navigation_for_session_owner(session_id, &url, history_update) + conn.record_same_document_navigation_for_owner(owner, &url, history_update) else { return; }; - for event_session_id in conn.page_event_session_ids_for_session_owner(session_id) { + for event_session_id in conn.page_event_session_ids_for_owner(owner) { let event = SameDocumentNavigationEvent { target_id: DevToolsTargetId::from(frame_id.as_str()), frame_id: DevToolsFrameId::from(frame_id.as_str()), @@ -3594,14 +3504,13 @@ fn emit_same_document_navigation_background_event( pub(crate) async fn emit_same_document_navigation_background_events_async( conn: &mut CdpConnection, out: &mut Vec, - session_id: Option<&str>, + owner: &CommandOwnerScope, navigations: Vec, ) { for navigation in navigations { + let session_id = owner.session_id(); let source_document = navigation.source_document(); - if !conn - .target_page_residence_identity_is_current_for_session(session_id, navigation.owner()) - { + if !conn.target_page_residence_identity_is_current(navigation.owner()) { tracing::debug!( session_id, ?source_document, @@ -3616,7 +3525,7 @@ pub(crate) async fn emit_same_document_navigation_background_events_async( let Ok(url) = Url::parse(&navigation.url) else { continue; }; - if conn.has_pending_document_navigation_for_session_owner(session_id) { + if conn.has_pending_document_navigation_for_owner(owner) { tracing::debug!( session_id, url = url.as_str(), @@ -3628,7 +3537,7 @@ pub(crate) async fn emit_same_document_navigation_background_events_async( emit_same_document_navigation_background_event( conn, out, - session_id, + owner, url, &navigation.navigation_type, navigation.history_update, diff --git a/moli-protocol/src/domains/page/navigation_commit.rs b/moli-protocol/src/domains/page/navigation_commit.rs index 51eb78b6ba..f8cdda5f74 100644 --- a/moli-protocol/src/domains/page/navigation_commit.rs +++ b/moli-protocol/src/domains/page/navigation_commit.rs @@ -507,17 +507,14 @@ async fn restore_and_commit_loaded_navigation_page_async( .unwrap_or_default(), ); } - let preload_channel_execution_context_ids = if conn - .target_owner_has_bidi_channel_preload_script_for_route( - state.owner.session_id(), - state.owner.session_owner_route(), - ) { - dedupe_preload_channel_execution_context_ids(std::mem::take( - &mut outcome.preload_channel_execution_context_ids, - )) - } else { - Vec::new() - }; + let preload_channel_execution_context_ids = + if conn.target_owner_has_bidi_channel_preload_script_for_owner(&state.owner) { + dedupe_preload_channel_execution_context_ids(std::mem::take( + &mut outcome.preload_channel_execution_context_ids, + )) + } else { + Vec::new() + }; let mut preload_channel_listener_events = Vec::new(); for execution_context_id in preload_channel_execution_context_ids { Box::pin( diff --git a/moli-protocol/src/domains/page/preload.rs b/moli-protocol/src/domains/page/preload.rs index 447ebf8b2b..0d97fed159 100644 --- a/moli-protocol/src/domains/page/preload.rs +++ b/moli-protocol/src/domains/page/preload.rs @@ -129,15 +129,9 @@ async fn append_loaded_page_document_start_script_for_owner_async( owner: &CommandOwnerScope, script: &DocumentStartScript, ) -> Result<(), String> { - let renderer_runtime_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); - let slot = conn.runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - )?; + let renderer_runtime_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); + let slot = conn.runtime_session_owner_slot_mut_for_owner(owner)?; if let Some(page) = slot.loaded_page_mut() { page.add_document_start_script_runtime_activity_async( renderer_runtime_inspector_session_id.as_deref(), @@ -155,10 +149,7 @@ async fn remove_loaded_page_document_start_script_for_owner_async( owner: &CommandOwnerScope, registry_key: &str, ) -> Result<(), String> { - let slot = conn.runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - )?; + let slot = conn.runtime_session_owner_slot_mut_for_owner(owner)?; if let Some(page) = slot.loaded_page_mut() { page.remove_document_start_script_by_registry_key_async(registry_key) .await @@ -503,10 +494,7 @@ async fn execute_devtools_single_route_add_preload_script_command( let identifier = if is_bidi_default_preload_command(&command) { execute_devtools_default_add_preload_script_command(conn, owner, command).await? } else { - if conn - .target_owner_identity_for_route(owner.session_id(), owner.session_owner_route()) - .is_none() - { + if conn.target_owner_identity_for_owner(owner).is_none() { return Err(preload_missing_owner_error(conn)); } let mut side_effects = CommandOutputPlan::default(); @@ -531,7 +519,7 @@ async fn execute_devtools_default_add_preload_script_command( ) -> Result { let script = document_start_script_from_add_preload_command(&command)?; let Some(browser_context_id) = conn - .target_owner_identity_for_route(owner.session_id(), owner.session_owner_route()) + .target_owner_identity_for_owner(owner) .map(|(browser_context_id, _)| browser_context_id) else { return Err(DevToolsError::new( @@ -558,13 +546,10 @@ async fn append_default_document_start_script_direct_async( identifier: String, script: &DocumentStartScript, ) -> Result { - let renderer_runtime_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_runtime_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); let Some(page) = conn - .runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) + .runtime_session_owner_slot_mut_for_owner(owner) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -582,7 +567,7 @@ async fn append_default_document_start_script_direct_async( .await .map_err(|error| devtools_preload_internal_error(error.to_string()))?; let Some(page) = conn - .runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) + .runtime_session_owner_slot_mut_for_owner(owner) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -600,23 +585,18 @@ async fn execute_devtools_single_route_remove_preload_script_command( ) -> Result<(), DevToolsError> { let protocol = command.context.protocol; let script_id = command.script_id.into_string(); - let owner_identity = - conn.target_owner_identity_for_route(owner.session_id(), owner.session_owner_route()); + let owner_identity = conn.target_owner_identity_for_owner(owner); let target_registry_key = owner_identity.as_ref().map(|(_, target_id)| { BrowserContext::target_document_start_script_registry_key(target_id.as_deref(), &script_id) }); - let remove_result = conn.with_target_owner_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |owner_state| { - remove_stored_document_start_script_registry_key( - owner_state, - None, - &script_id, - target_registry_key.clone(), - ) - }, - ); + let remove_result = conn.with_target_owner_state_for_owner_mut(owner, |owner_state| { + remove_stored_document_start_script_registry_key( + owner_state, + None, + &script_id, + target_registry_key.clone(), + ) + }); let Some((mut removed, mut registry_key)) = remove_result else { return Err(preload_missing_owner_error(conn)); }; @@ -648,7 +628,7 @@ async fn remove_document_start_script_direct_async( return Ok(()); }; let Some(page) = conn - .runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) + .runtime_session_owner_slot_mut_for_owner(owner) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -662,7 +642,7 @@ async fn remove_document_start_script_direct_async( .await .map_err(|error| devtools_preload_internal_error(error.to_string()))?; let Some(page) = conn - .runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) + .runtime_session_owner_slot_mut_for_owner(owner) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -996,8 +976,9 @@ fn find_preload_script_route(conn: &mut CdpConnection, script_id: &str) -> Optio let Some(route) = conn.target_session_route_for_target_id(&target_id) else { continue; }; + let owner = CommandOwnerScope::for_route(route.clone()); let has_script = conn - .target_owner_state_for_route(None, Some(&route)) + .target_owner_state_for_owner(&owner) .is_some_and(|owner_state| { owner_state .document_start_scripts @@ -1298,7 +1279,7 @@ fn start_create_isolated_world_initial_navigation_or_renderer_phase( mut task: CreateIsolatedWorldCommandTask, ) -> PageCommandTaskStep { let should_start_target_url_navigation = - conn.runtime_session_owner_can_start_initial_document_navigation(owner.session_id()); + conn.runtime_session_owner_can_start_initial_document_navigation_for_owner(&owner); if !should_start_target_url_navigation { return start_create_isolated_world_frame_or_world_phase(conn, command_id, owner, task); } @@ -1368,11 +1349,8 @@ fn start_create_isolated_world_frame_or_world_phase( let frame_id = (task.params.frame_id != task.target_id).then(|| task.params.frame_id.clone()); let world_name = task.params.world_name.clone(); let grant_universal_access = task.params.grant_universal_access; - let renderer_runtime_inspector_session_id = conn - .target_renderer_runtime_inspector_session_id_for_route( - owner.session_id(), - owner.session_owner_route(), - ); + let renderer_runtime_inspector_session_id = + conn.target_renderer_runtime_inspector_session_id_for_owner(&owner); let page = match loaded_page_mut_for_create_isolated_world_renderer_command(conn, &owner, &mut task) { Ok(page) => page, @@ -1402,7 +1380,7 @@ fn loaded_page_mut_for_create_isolated_world_renderer_command<'a>( task: &mut CreateIsolatedWorldCommandTask, ) -> Result<&'a mut moli_core::page::Page, CommandOutputPlan> { let slot = conn - .runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) + .runtime_session_owner_slot_mut_for_owner(owner) .map_err(|error| CommandOutputPlan::error(-32000, error))?; task.pending_renderer_agent_attachment_id = Some( slot.current_renderer_attachment() @@ -1421,7 +1399,7 @@ fn create_isolated_world_renderer_completion_is_stale( let Some(expected_attachment_id) = task.pending_renderer_agent_attachment_id else { return false; }; - conn.runtime_session_owner_slot_for_route(owner.session_id(), owner.session_owner_route()) + conn.runtime_session_owner_slot_for_owner(owner) .map(|slot| { slot.current_renderer_attachment() .map(|attachment| attachment.id()) @@ -1627,10 +1605,7 @@ pub(super) async fn complete_pending_create_isolated_world_command( }; let completed_world = { let Some(page) = conn - .runtime_session_owner_slot_mut_for_route( - owner.session_id(), - owner.session_owner_route(), - ) + .runtime_session_owner_slot_mut_for_owner(owner) .ok() .and_then(|slot| slot.loaded_page_mut()) else { @@ -1742,26 +1717,22 @@ async fn add_script_to_evaluate_on_new_document_direct_async( command_context: &mut CommandDispatchContext, ) -> Result { let script = document_start_script_from_add_preload_command(&command)?; - let session_id = owner.session_id(); - let owner_route = owner.session_owner_route(); let renderer_inspector_session_id = - conn.target_renderer_runtime_inspector_session_id_for_route(session_id, owner_route); + conn.target_renderer_runtime_inspector_session_id_for_owner(owner); let script_owner_session = (command.context.protocol == DevToolsProtocol::Cdp).then(|| { DevToolsSessionKey::from_wire_session_id(renderer_inspector_session_id.as_deref()) }); let target_id = conn - .target_owner_identity_for_route(session_id, owner_route) + .target_owner_identity_for_owner(owner) .and_then(|(_, target_id)| target_id); - let Some(recorded) = - conn.with_target_owner_state_for_route_mut(session_id, owner_route, |owner_state| { - record_document_start_script( - owner_state, - target_id.as_deref(), - script_owner_session.as_ref(), - &script, - ) - }) - else { + let Some(recorded) = conn.with_target_owner_state_for_owner_mut(owner, |owner_state| { + record_document_start_script( + owner_state, + target_id.as_deref(), + script_owner_session.as_ref(), + &script, + ) + }) else { return Err(preload_missing_owner_error(conn)); }; let identifier = recorded.identifier.clone(); @@ -1771,7 +1742,7 @@ async fn add_script_to_evaluate_on_new_document_direct_async( } let pending_run_immediately = { let renderer_runtime_inspector_session_id = renderer_inspector_session_id; - let slot = match conn.runtime_session_owner_slot_mut_for_route(session_id, owner_route) { + let slot = match conn.runtime_session_owner_slot_mut_for_owner(owner) { Ok(slot) => slot, Err(error) => return Err(devtools_preload_internal_error(error)), }; @@ -1799,7 +1770,7 @@ async fn add_script_to_evaluate_on_new_document_direct_async( .map_err(|error| devtools_preload_internal_error(error.to_string()))?; let (result, output) = { let slot = conn - .runtime_session_owner_slot_mut_for_route(session_id, owner_route) + .runtime_session_owner_slot_mut_for_owner(owner) .map_err(devtools_preload_internal_error)?; let page = slot.loaded_page_mut().ok_or_else(|| { devtools_preload_internal_error("NoDocumentLoaded".to_owned()) diff --git a/moli-protocol/src/domains/page/resource_search.rs b/moli-protocol/src/domains/page/resource_search.rs index 66474b799a..3e6347c53d 100644 --- a/moli-protocol/src/domains/page/resource_search.rs +++ b/moli-protocol/src/domains/page/resource_search.rs @@ -299,7 +299,7 @@ fn complete_error(message: impl Into) -> PageCommandTaskStep { } fn loaded_page<'a>(conn: &'a mut CdpConnection, owner: &CommandOwnerScope) -> Option<&'a mut Page> { - conn.runtime_session_owner_slot_mut_for_route(owner.session_id(), owner.session_owner_route()) + conn.runtime_session_owner_slot_mut_for_owner(owner) .ok()? .loaded_page_mut() } diff --git a/moli-protocol/src/domains/page/termination.rs b/moli-protocol/src/domains/page/termination.rs index 03a5303c26..7fbafd18fd 100644 --- a/moli-protocol/src/domains/page/termination.rs +++ b/moli-protocol/src/domains/page/termination.rs @@ -117,7 +117,7 @@ fn take_pending_fetch_state_for_owner( Vec<(String, crate::conn::PendingSubresourceFetchAuthRequest)>, Vec<(String, crate::conn::PendingSubresourceFetchResponseRequest)>, ) { - conn.take_pending_fetch_state_for_route(owner.session_id(), owner.session_owner_route()) + conn.take_pending_fetch_state_for_owner(owner) .unwrap_or_else(|| { ( Vec::new(), @@ -179,7 +179,6 @@ async fn fail_pending_fetch_state_for_owner_background_events_async( crate::conn::PendingSubresourceFetchResponseRequest, )>, ) -> Option { - let session_id = owner.session_id(); // A protocol navigation waiter may expose an operation-specific failure, // while Network.loadingFailed must retain the underlying net error. For // Page.stopLoading Chromium reports ERR_ABORTED/canceled=true even though @@ -235,13 +234,12 @@ async fn fail_pending_fetch_state_for_owner_background_events_async( merge_renderer_output_predecessor(&mut renderer_output_predecessor, predecessor); } for (_, pending) in pending_subresource_fetches { - if !conn.pending_subresource_fetch_request_residence_is_current(session_id, &pending) { + if !conn.pending_subresource_fetch_request_residence_is_current(&pending) { continue; } match conn - .fail_pending_subresource_fetch_for_route_async( - session_id, - owner.session_owner_route(), + .fail_pending_subresource_fetch_for_owner_async( + owner, pending.internal_id, subresource_error_text.to_owned(), ) @@ -262,15 +260,12 @@ async fn fail_pending_fetch_state_for_owner_background_events_async( } } for (_, pending) in pending_subresource_auths { - if !conn - .target_page_residence_identity_is_current_for_session(session_id, &pending.page_owner) - { + if !conn.target_page_residence_identity_is_current(&pending.page_owner) { continue; } match conn - .fail_pending_subresource_auth_for_route_async( - session_id, - owner.session_owner_route(), + .fail_pending_subresource_auth_for_owner_async( + owner, pending.internal_id, subresource_error_text.to_owned(), ) @@ -288,15 +283,12 @@ async fn fail_pending_fetch_state_for_owner_background_events_async( } } for (_, pending) in pending_subresource_responses { - if !conn - .target_page_residence_identity_is_current_for_session(session_id, &pending.page_owner) - { + if !conn.target_page_residence_identity_is_current(&pending.page_owner) { continue; } match conn - .fail_pending_subresource_response_for_route_async( - session_id, - owner.session_owner_route(), + .fail_pending_subresource_response_for_owner_async( + owner, pending.internal_id, subresource_error_text.to_owned(), ) @@ -337,10 +329,9 @@ fn fail_crashed_subresource_fetches_background_events( pending_subresource_responses: Vec<(String, PendingSubresourceFetchResponseRequest)>, ) { let loader_id = conn - .current_document_loader_id_for_route(owner.session_id(), owner.session_owner_route()) + .current_document_loader_id_for_owner(owner) .unwrap_or_else(|| DEFAULT_LOADER_ID.to_owned()); - let event_session_ids = - conn.network_event_session_ids_for_route(owner.session_id(), owner.session_owner_route()); + let event_session_ids = conn.network_event_session_ids_for_owner(owner); let timestamp = monotonic_timestamp_seconds(); let mut emit_failure = @@ -404,9 +395,7 @@ pub(super) async fn complete_stop_loading_command_dispatch( owner: &CommandOwnerScope, ) -> PageCommandTaskStep { let mut out = Vec::new(); - let session_id = owner.session_id(); - if let Ok(slot) = - conn.runtime_session_owner_slot_mut_for_route(session_id, owner.session_owner_route()) + if let Ok(slot) = conn.runtime_session_owner_slot_mut_for_owner(owner) && let Some(page) = slot.loaded_page_mut() && let Err(error) = page.stop_document_lifecycle_async().await { @@ -473,9 +462,7 @@ pub(super) async fn complete_crash_command_dispatch( ) -> PageCommandTaskStep { let mut out = Vec::new(); let session_id = owner.session_id(); - let Some((_, target_id)) = - conn.target_owner_identity_for_route(session_id, owner.session_owner_route()) - else { + let Some((_, target_id)) = conn.target_owner_identity_for_owner(owner) else { return PageCommandTaskStep::Complete(CommandOutputPlan::error_without_session( -31998, super::missing_page_target_error_message(conn, session_id), @@ -501,10 +488,7 @@ pub(super) async fn complete_crash_command_dispatch( // it never enters a V8InspectorSession or the ordinary target IO task FIFO. // Seal both DevTools receivers and interrupt active V8 synchronously so // target retirement cannot wait behind earlier JavaScript or IO work. - if let Ok(page) = conn.loaded_page_mut_for_interruptible_protocol_access_for_route( - session_id, - owner.session_owner_route(), - ) { + if let Ok(page) = conn.loaded_page_mut_for_interruptible_protocol_access_for_owner(owner) { page.crash_devtools_target_from_io(); } @@ -513,8 +497,7 @@ pub(super) async fn complete_crash_command_dispatch( // Page; otherwise a late completion from (for example) the primary // session can wait forever on a response sender owned by the retired // renderer while the crash was issued by an auxiliary session. - let target_inspector_session_ids = - conn.page_event_session_ids_for_route(session_id, owner.session_owner_route()); + let target_inspector_session_ids = conn.page_event_session_ids_for_owner(owner); let mut pending_await_events = Vec::new(); for inspector_session_id in &target_inspector_session_ids { let inspector_owner = inspector_session_id @@ -566,26 +549,19 @@ async fn mark_page_target_crashed_background_events_async( owner: &CommandOwnerScope, target_id: &str, ) -> Vec { - let inspector_session_ids = - conn.page_event_session_ids_for_route(owner.session_id(), owner.session_owner_route()); + let inspector_session_ids = conn.page_event_session_ids_for_owner(owner); for inspector_session_id in &inspector_session_ids { let inspector_owner = inspector_session_id .as_deref() .map(CommandOwnerScope::for_session) .unwrap_or_else(|| owner.clone()); - let _ = conn.with_target_devtools_session_state_for_route_mut( - inspector_owner.session_id(), - inspector_owner.session_owner_route(), - |state| { - state - .runtime_session_state - .record_inspector_target_crashed(); - }, - ); + let _ = conn.with_target_devtools_session_state_for_owner_mut(&inspector_owner, |state| { + state + .runtime_session_state + .record_inspector_target_crashed(); + }); } - let _ = conn - .mark_target_crashed_for_route_async(owner.session_id(), owner.session_owner_route()) - .await; + let _ = conn.mark_target_crashed_for_owner_async(owner).await; let mut out = inspector_session_ids .into_iter() .map(|inspector_session_id| { @@ -615,9 +591,7 @@ pub(super) async fn complete_close_command_dispatch( ) -> PageCommandTaskStep { let mut out = Vec::new(); let session_id = owner.session_id(); - let Some((_, target_id)) = - conn.target_owner_identity_for_route(session_id, owner.session_owner_route()) - else { + let Some((_, target_id)) = conn.target_owner_identity_for_owner(owner) else { return PageCommandTaskStep::Complete(CommandOutputPlan::error_without_session( -31998, super::missing_page_target_error_message(conn, session_id), @@ -686,10 +660,7 @@ pub(crate) async fn complete_page_target_termination_owner_action_async( let (owner_scope, expected_target_id) = action.into_parts(); let mut out = Vec::new(); let current_target_id = conn - .target_owner_identity_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) + .target_owner_identity_for_owner(&owner_scope) .and_then(|(_, target_id)| target_id); if current_target_id.as_deref() != Some(expected_target_id.as_str()) { return crate::conn::CdpTurnOutcome::new_with_protocol_events( diff --git a/moli-protocol/src/domains/page/tests/lifecycle.rs b/moli-protocol/src/domains/page/tests/lifecycle.rs index ca8cbea020..82cdafda9f 100644 --- a/moli-protocol/src/domains/page/tests/lifecycle.rs +++ b/moli-protocol/src/domains/page/tests/lifecycle.rs @@ -1575,7 +1575,9 @@ async fn runtime_document_close_emits_lifecycle_for_repeated_playwright_set_cont for iteration in 0..32 { let previous_document = ctx .conn - .target_root_document_lifecycle_identity_for_route(Some("SID-1"), None) + .target_root_document_lifecycle_identity_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), + ) .expect("the previous replacement must retain an exact Document identity"); let id = 100 + iteration; ctx.process_async(json!({ @@ -3679,13 +3681,18 @@ async fn screencast_commands_update_page_session_state() { assert_eq!(config.every_nth_frame(), 1); assert_eq!( - ctx.conn - .begin_page_screencast_capture_for_route(Some("SID-screencast"), None, 1), + ctx.conn.begin_page_screencast_capture_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-screencast"), + 1 + ), Some(true) ); assert_eq!( - ctx.conn - .complete_page_screencast_capture_for_route(Some("SID-screencast"), None, 1, true,), + ctx.conn.complete_page_screencast_capture_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-screencast"), + 1, + true, + ), Some(true) ); @@ -4164,17 +4171,15 @@ async fn repeated_start_invalidates_old_screencast_ack_generation() { let generation = i32::try_from(id - 62).expect("small screencast generation"); assert_eq!( - ctx.conn.begin_page_screencast_capture_for_route( - Some("SID-screencast-generation"), - None, + ctx.conn.begin_page_screencast_capture_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-screencast-generation"), generation, ), Some(true) ); assert_eq!( - ctx.conn.complete_page_screencast_capture_for_route( - Some("SID-screencast-generation"), - None, + ctx.conn.complete_page_screencast_capture_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-screencast-generation"), generation, true, ), diff --git a/moli-protocol/src/domains/performance.rs b/moli-protocol/src/domains/performance.rs index f93d0a4166..db827dd486 100644 --- a/moli-protocol/src/domains/performance.rs +++ b/moli-protocol/src/domains/performance.rs @@ -1,7 +1,6 @@ use crate::conn::{ - CdpConnection, CdpRendererCommandAccess, CdpSessionRoute, Cmd, CommandOwnerScope, - PerformanceTimeDomain, RendererCommandCorrelation, RendererCommandDescriptor, - monotonic_timestamp_seconds, + CdpConnection, CdpRendererCommandAccess, Cmd, CommandOwnerScope, PerformanceTimeDomain, + RendererCommandCorrelation, RendererCommandDescriptor, monotonic_timestamp_seconds, }; use crate::domains::actions::PerformanceAction; use crate::domains::command_output::CommandOutputPlan; @@ -114,16 +113,16 @@ impl CompletedPerformanceCommandDispatch { fn loaded_page_mut_for_renderer_access<'a>( conn: &'a mut CdpConnection, - session_id: Option<&str>, renderer_access: CdpRendererCommandAccess, - owner_route: Option<&CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Result<&'a mut Page, String> { match renderer_access { CdpRendererCommandAccess::MainThread => { - conn.loaded_page_mut_for_protocol_access_for_route(session_id, owner_route) + conn.loaded_page_mut_for_protocol_access_for_owner(owner) + } + CdpRendererCommandAccess::Io => { + conn.loaded_page_mut_for_interruptible_protocol_access_for_owner(owner) } - CdpRendererCommandAccess::Io => conn - .loaded_page_mut_for_interruptible_protocol_access_for_route(session_id, owner_route), CdpRendererCommandAccess::OwnerIndependent => { Err("Performance.getMetrics requires a renderer Page".to_owned()) } @@ -236,19 +235,15 @@ pub(crate) fn try_start_performance_command_dispatch( let owner_scope = CommandOwnerScope::capture(conn, cmd.session_id); if renderer_access == CdpRendererCommandAccess::Io { let (renderer_page, attachment_id, snapshot) = { - let page = match loaded_page_mut_for_renderer_access( - conn, - cmd.session_id, - renderer_access, - owner_scope.session_owner_route(), - ) { - Ok(page) => page, - Err(_) => { - return PerformanceCommandTaskStep::Complete( - default_metrics_command_output_plan(), - ); - } - }; + let page = + match loaded_page_mut_for_renderer_access(conn, renderer_access, &owner_scope) { + Ok(page) => page, + Err(_) => { + return PerformanceCommandTaskStep::Complete( + default_metrics_command_output_plan(), + ); + } + }; ( crate::conn::RendererPageResidenceIdentity::from_page(page), page.renderer_agent_attachment_id(), @@ -261,13 +256,8 @@ pub(crate) fn try_start_performance_command_dispatch( if cmd.id.is_none() || response_delivery == moli_page_types::RendererInspectorResponseDelivery::CommandReply { - let page = loaded_page_mut_for_renderer_access( - conn, - cmd.session_id, - renderer_access, - owner_scope.session_owner_route(), - ) - .expect("the captured Performance Page must remain loaded synchronously"); + let page = loaded_page_mut_for_renderer_access(conn, renderer_access, &owner_scope) + .expect("the captured Performance Page must remain loaded synchronously"); let (pending, snapshot) = page.start_performance_metric_snapshot_from_io(); return PerformanceCommandTaskStep::Pending(PendingPerformanceCommandDispatch { command_id: cmd.id, @@ -312,26 +302,21 @@ pub(crate) fn try_start_performance_command_dispatch( response_rx.is_none(), "Performance session output must not allocate a command-reply receiver", ); - let pending = loaded_page_mut_for_renderer_access( - conn, - cmd.session_id, - renderer_access, - owner_scope.session_owner_route(), - ) - .ok() - .filter(|page| { - crate::conn::RendererPageResidenceIdentity::from_page(page) == renderer_page - && page.renderer_agent_attachment_id() == Some(attachment_id) - }) - .ok_or_else(|| "Performance renderer attachment changed before IO dispatch".to_owned()) - .and_then(|page| { - page.start_performance_get_metrics_from_io_with_response( - renderer_inspector_session_id, - result, - response, - ) - .map_err(|error| error.to_string()) - }); + let pending = loaded_page_mut_for_renderer_access(conn, renderer_access, &owner_scope) + .ok() + .filter(|page| { + crate::conn::RendererPageResidenceIdentity::from_page(page) == renderer_page + && page.renderer_agent_attachment_id() == Some(attachment_id) + }) + .ok_or_else(|| "Performance renderer attachment changed before IO dispatch".to_owned()) + .and_then(|page| { + page.start_performance_get_metrics_from_io_with_response( + renderer_inspector_session_id, + result, + response, + ) + .map_err(|error| error.to_string()) + }); let pending = match pending { Ok(pending) => pending, Err(error) => { @@ -356,12 +341,7 @@ pub(crate) fn try_start_performance_command_dispatch( }), }); } - let page = match loaded_page_mut_for_renderer_access( - conn, - cmd.session_id, - renderer_access, - owner_scope.session_owner_route(), - ) { + let page = match loaded_page_mut_for_renderer_access(conn, renderer_access, &owner_scope) { Ok(page) => page, Err(_) => { return PerformanceCommandTaskStep::Complete(default_metrics_command_output_plan()); @@ -412,33 +392,23 @@ pub(crate) async fn complete_pending_performance_command( renderer_page, completed, } = completed; - let session_id = owner_scope.session_id().map(str::to_owned); let snapshot = match completed { Ok(CompletedPerformanceRendererCommand::Main(completed_page)) => { - loaded_page_mut_for_renderer_access( - conn, - session_id.as_deref(), - renderer_access, - owner_scope.session_owner_route(), - ) - .ok() - .filter(|page| { - crate::conn::RendererPageResidenceIdentity::from_page(page) == renderer_page - }) - .and_then(|page| page.finish_performance_metric_snapshot(completed_page).ok()) - .unwrap_or_default() + loaded_page_mut_for_renderer_access(conn, renderer_access, &owner_scope) + .ok() + .filter(|page| { + crate::conn::RendererPageResidenceIdentity::from_page(page) == renderer_page + }) + .and_then(|page| page.finish_performance_metric_snapshot(completed_page).ok()) + .unwrap_or_default() } Ok(CompletedPerformanceRendererCommand::IoCommandReply(snapshot)) => { - let remains_current = loaded_page_mut_for_renderer_access( - conn, - session_id.as_deref(), - renderer_access, - owner_scope.session_owner_route(), - ) - .ok() - .is_some_and(|page| { - crate::conn::RendererPageResidenceIdentity::from_page(page) == renderer_page - }); + let remains_current = + loaded_page_mut_for_renderer_access(conn, renderer_access, &owner_scope) + .ok() + .is_some_and(|page| { + crate::conn::RendererPageResidenceIdentity::from_page(page) == renderer_page + }); if remains_current { snapshot } else { @@ -456,11 +426,8 @@ pub(crate) async fn complete_pending_performance_command( plan.set_renderer_output_predecessor(predecessor); return plan; } - if !conn.take_renderer_call_if_correlation_matches_for_route( - session_id.as_deref(), - owner_scope.session_owner_route(), - correlation, - ) { + if !conn.take_renderer_call_if_correlation_matches_for_owner(&owner_scope, correlation) + { return CommandOutputPlan::default(); } RendererPerformanceMetricSnapshot::default() diff --git a/moli-protocol/src/domains/runtime/activity.rs b/moli-protocol/src/domains/runtime/activity.rs index e7101725d5..22186d8d62 100644 --- a/moli-protocol/src/domains/runtime/activity.rs +++ b/moli-protocol/src/domains/runtime/activity.rs @@ -2,7 +2,7 @@ use crate::domains::activity::{ ProtocolOutputPayloads, ProtocolOutputProjectionContext, ProtocolOutputSink, ProtocolOutputSlot, }; use crate::{ - conn::{BackgroundProtocolEvent, CdpConnection, CommandOwnerScope}, + conn::{BackgroundProtocolEvent, CdpConnection, CdpSessionRoute, CommandOwnerScope}, domains::command_output::protocol_message_background_event_for_target, domains::runtime_context_events::{ RuntimeContextProtocolEvent, apply_runtime_context_protocol_event_side_effects_typed, @@ -57,18 +57,19 @@ struct RuntimeInspectorMessageBatch { /// Projection authority for one prepared Inspector batch. /// -/// Ordinary observations remain tied to the exact Page attachment that -/// produced them. A retired terminal response is a distinct state rather than -/// an absent attachment: its exact renderer correlation was already consumed -/// at ingress, and no notification or renderer state can inhabit this variant. +/// Document and Worker observations remain tied to their concrete attachment. +/// Terminal responses instead belong to the DevTools session that registered +/// their renderer call. This mirrors Chromium's browser-side call-id journal: +/// replacing a document does not invalidate a response which already won that +/// session correlation, but it never authorizes observations from the retired +/// document. #[derive(Clone, Debug, PartialEq)] enum RuntimeInspectorMessageAuthority { CurrentPage(crate::conn::TargetPageProtocolAttachmentIdentity), CurrentWorker(crate::conn::TargetWorkerProtocolAttachmentIdentity), - AuthorizedRetiredTerminal { - browser_context_id: String, - target_id: Option, - session_id: Option, + SessionResponse { + owner: CommandOwnerScope, + expected_route: CdpSessionRoute, }, } @@ -77,7 +78,7 @@ impl RuntimeInspectorMessageAuthority { match self { Self::CurrentPage(attachment) => attachment.session_id(), Self::CurrentWorker(attachment) => Some(attachment.session_id()), - Self::AuthorizedRetiredTerminal { session_id, .. } => session_id.as_deref(), + Self::SessionResponse { owner, .. } => owner.session_id(), } } @@ -87,34 +88,22 @@ impl RuntimeInspectorMessageAuthority { conn.target_page_protocol_attachment_identity_is_current(attachment) } Self::CurrentWorker(attachment) => attachment.is_current(), - Self::AuthorizedRetiredTerminal { - browser_context_id, - target_id, - session_id, - } => { - let Some((current_browser_context_id, current_target_id)) = - conn.target_owner_identity_for_session(session_id.as_deref()) - else { - return false; - }; - let current_target_id = current_target_id.or_else(|| { - conn.browser_context_by_id(¤t_browser_context_id) - .and_then(|context| context.active_target_id_owned()) - }); - current_browser_context_id == *browser_context_id && current_target_id == *target_id - } + Self::SessionResponse { + owner, + expected_route, + } => owner.resolve_route(conn).as_ref() == Some(expected_route), } } - fn command_owner(&self) -> Option { + fn command_owner(&self) -> crate::conn::CommandOwnerScope { match self { - Self::CurrentPage(attachment) => Some( - crate::conn::CommandOwnerScope::for_page_attachment(attachment), - ), - Self::CurrentWorker(attachment) => { - Some(CommandOwnerScope::for_session(attachment.session_id())) + Self::CurrentPage(attachment) => { + crate::conn::CommandOwnerScope::for_page_attachment(attachment) } - Self::AuthorizedRetiredTerminal { .. } => None, + Self::CurrentWorker(attachment) => { + CommandOwnerScope::for_session(attachment.session_id()) + } + Self::SessionResponse { owner, .. } => owner.clone(), } } } @@ -218,13 +207,10 @@ impl RuntimeOutputProjectionStep { session_id.as_deref(), ); for execution_context_id in batch.created_execution_context_ids { - let Some(owner) = owner.as_ref() else { - continue; - }; Box::pin( super::start_bidi_preload_channel_listeners_for_execution_context_background_events_async( conn, - owner, + &owner, execution_context_id, context.command.protocol_events_mut(), ), @@ -269,15 +255,49 @@ pub(in crate::domains) async fn project_runtime_inspector_post_response_messages } impl RuntimePreparedOutputs { + fn append_inspector_message( + &mut self, + order: RendererRuntimeInspectorMessageResponseOrder, + authority: RuntimeInspectorMessageAuthority, + message: RuntimeInspectorMessage, + ) { + let batches = match order { + RendererRuntimeInspectorMessageResponseOrder::BeforeCommandResponse => { + &mut self.inspector_message_batches + } + RendererRuntimeInspectorMessageResponseOrder::AfterCommandResponse => { + &mut self.post_response_inspector_message_batches + } + }; + let created_execution_context_id = message.created_execution_context_id(); + if let Some(last) = batches.last_mut() + && last.authority == authority + { + last.messages.push(message); + if let Some(execution_context_id) = created_execution_context_id + && !last + .created_execution_context_ids + .contains(&execution_context_id) + { + last.created_execution_context_ids + .push(execution_context_id); + } + return; + } + batches.push(RuntimeInspectorMessageBatch { + authority, + messages: vec![message], + created_execution_context_ids: created_execution_context_id.into_iter().collect(), + }); + } + pub(crate) fn from_renderer_runtime_binding_call( conn: &CdpConnection, owner: &CommandOwnerScope, call: moli_core::page::PendingRuntimeBindingCall, ) -> Self { - let Some(attachment) = conn.target_page_protocol_attachment_identity_for_route( - owner.session_id(), - owner.session_owner_route(), - ) else { + let Some(attachment) = conn.target_page_protocol_attachment_identity_for_owner(owner) + else { return Self::default(); }; Self { @@ -292,13 +312,26 @@ impl RuntimePreparedOutputs { } } - pub(crate) fn from_renderer_runtime_inspector_message_batches( + pub(crate) fn from_page_renderer_runtime_inspector_message_batches( conn: &mut CdpConnection, source_owner: &CommandOwnerScope, - batches: &[RendererRuntimeInspectorMessageBatch], + source_batches: Vec, ) -> Self { + let current_batches = conn.route_current_renderer_inspector_output_for_owner( + source_owner, + source_batches.clone(), + ); + let observations_are_current = !current_batches.is_empty(); + let batches = if observations_are_current { + current_batches + } else { + source_batches + }; let mut outputs = Self::default(); - for batch in batches.iter().filter(|batch| !batch.messages.is_empty()) { + for batch in batches + .into_iter() + .filter(|batch| !batch.messages.is_empty()) + { let Some(attachment) = conn .target_page_protocol_attachment_identity_for_renderer_inspector_owner( source_owner, @@ -307,47 +340,53 @@ impl RuntimePreparedOutputs { else { continue; }; - let mut renderer_messages = batch.messages.clone(); - if let Some(renderer_agent_attachment_id) = batch.renderer_agent_attachment_id() { - conn.restore_frontend_command_ids_in_devtools_session_output( - attachment.session_id(), - renderer_agent_attachment_id, - &mut renderer_messages, + let response_owner = CommandOwnerScope::for_page_attachment(&attachment); + let response_route = response_owner.resolve_route(conn); + let renderer_agent_attachment_id = batch.renderer_agent_attachment_id(); + let order = batch.command_response_order(); + for message in batch.messages { + let is_terminal_response = matches!( + &message, + RendererRuntimeInspectorMessage::Protocol(message) + if message.renderer_call_id().is_some() ); - } - if renderer_messages.is_empty() { - continue; - } - let messages = renderer_messages - .into_iter() - .map(|message| { - RuntimeInspectorMessage::from_renderer_message( - message, - attachment.page_owner().target_id(), - ) - }) - .collect::>(); - let mut created_execution_context_ids = Vec::new(); - for execution_context_id in messages - .iter() - .filter_map(RuntimeInspectorMessage::created_execution_context_id) - { - if !created_execution_context_ids.contains(&execution_context_id) { - created_execution_context_ids.push(execution_context_id); + if is_terminal_response { + let Some(expected_route) = response_route.clone() else { + continue; + }; + let mut response = vec![message]; + conn.restore_frontend_command_ids_in_devtools_session_output_for_owner( + &response_owner, + renderer_agent_attachment_id, + &mut response, + observations_are_current, + ); + let Some(response) = response.pop() else { + continue; + }; + outputs.append_inspector_message( + order, + RuntimeInspectorMessageAuthority::SessionResponse { + owner: response_owner.clone(), + expected_route, + }, + RuntimeInspectorMessage::from_renderer_message( + response, + attachment.page_owner().target_id(), + ), + ); + continue; } - } - let prepared = RuntimeInspectorMessageBatch { - authority: RuntimeInspectorMessageAuthority::CurrentPage(attachment), - messages, - created_execution_context_ids, - }; - match batch.command_response_order() { - RendererRuntimeInspectorMessageResponseOrder::BeforeCommandResponse => { - outputs.inspector_message_batches.push(prepared); + if observations_are_current { + outputs.append_inspector_message( + order, + RuntimeInspectorMessageAuthority::CurrentPage(attachment.clone()), + RuntimeInspectorMessage::from_renderer_message( + message, + attachment.page_owner().target_id(), + ), + ); } - RendererRuntimeInspectorMessageResponseOrder::AfterCommandResponse => outputs - .post_response_inspector_message_batches - .push(prepared), } } outputs @@ -366,122 +405,45 @@ impl RuntimePreparedOutputs { else { return Self::default(); }; - let mut renderer_messages = batch.messages.clone(); - conn.restore_frontend_command_ids_in_worker_devtools_session_output( - session_id, - &mut renderer_messages, - ); - if renderer_messages.is_empty() { + let response_owner = CommandOwnerScope::for_session(session_id); + let Some(response_route) = response_owner.resolve_route(conn) else { return Self::default(); - } - let target_id = attachment.target_id().to_owned(); - let prepared = RuntimeInspectorMessageBatch { - authority: RuntimeInspectorMessageAuthority::CurrentWorker(attachment), - messages: renderer_messages - .into_iter() - .map(|message| { - RuntimeInspectorMessage::from_renderer_message(message, Some(&target_id)) - }) - .collect(), - // Worker contexts never own Page/BiDi preload-channel listeners. - created_execution_context_ids: Vec::new(), }; + let target_id = attachment.target_id().to_owned(); let mut outputs = Self::default(); - match batch.command_response_order() { - RendererRuntimeInspectorMessageResponseOrder::BeforeCommandResponse => { - outputs.inspector_message_batches.push(prepared); - } - RendererRuntimeInspectorMessageResponseOrder::AfterCommandResponse => { - outputs - .post_response_inspector_message_batches - .push(prepared); - } - } - outputs - } - - /// Preserves only terminal session responses from an attachment that was - /// current when the response lease was claimed but retired before its Page - /// journal crossed protocol ingress. - /// - /// The exact renderer correlation is consumed here. This makes the - /// resulting response an already-authorized session fact, while all - /// notifications, context events, V8 state, and remote-object projection - /// from the retired document are discarded. - pub(crate) fn from_retired_renderer_runtime_inspector_session_responses( - conn: &mut CdpConnection, - source_owner: &CommandOwnerScope, - batches: &[RendererRuntimeInspectorMessageBatch], - ) -> Self { - let mut outputs = Self::default(); - for batch in batches { - let Some(renderer_agent_attachment_id) = batch.renderer_agent_attachment_id() else { - continue; - }; - let Some(protocol_attachment) = conn - .target_page_protocol_attachment_identity_for_renderer_inspector_owner( - source_owner, - batch.session.wire_session_id(), - ) - else { - continue; - }; - let session_id = protocol_attachment.session_id().map(str::to_owned); - if conn.renderer_agent_attachment_is_current_for_session_owner( - session_id.as_deref(), - renderer_agent_attachment_id, - ) { - continue; - } - - let mut responses = batch - .messages - .iter() - .filter(|message| { - matches!( - message, - RendererRuntimeInspectorMessage::Protocol(message) - if message.renderer_call_id().is_some() - ) - }) - .cloned() - .collect::>(); - conn.restore_frontend_command_ids_in_retired_devtools_session_output( - session_id.as_deref(), - renderer_agent_attachment_id, - &mut responses, + let order = batch.command_response_order(); + for message in batch.messages.clone() { + let is_terminal_response = matches!( + &message, + RendererRuntimeInspectorMessage::Protocol(message) + if message.renderer_call_id().is_some() ); - if responses.is_empty() { + if is_terminal_response { + let mut response = vec![message]; + conn.restore_frontend_command_ids_in_devtools_session_output_for_owner( + &response_owner, + None, + &mut response, + true, + ); + let Some(response) = response.pop() else { + continue; + }; + outputs.append_inspector_message( + order, + RuntimeInspectorMessageAuthority::SessionResponse { + owner: response_owner.clone(), + expected_route: response_route.clone(), + }, + RuntimeInspectorMessage::from_renderer_message(response, Some(&target_id)), + ); continue; } - let target_id = protocol_attachment.page_owner().target_id(); - let messages = responses - .into_iter() - .map(|message| RuntimeInspectorMessage::from_renderer_message(message, target_id)) - .collect(); - let prepared = RuntimeInspectorMessageBatch { - authority: RuntimeInspectorMessageAuthority::AuthorizedRetiredTerminal { - browser_context_id: protocol_attachment - .page_owner() - .browser_context_id() - .to_owned(), - target_id: protocol_attachment - .page_owner() - .target_id() - .map(str::to_owned), - session_id, - }, - messages, - created_execution_context_ids: Vec::new(), - }; - match batch.command_response_order() { - RendererRuntimeInspectorMessageResponseOrder::BeforeCommandResponse => { - outputs.inspector_message_batches.push(prepared); - } - RendererRuntimeInspectorMessageResponseOrder::AfterCommandResponse => outputs - .post_response_inspector_message_batches - .push(prepared), - } + outputs.append_inspector_message( + order, + RuntimeInspectorMessageAuthority::CurrentWorker(attachment.clone()), + RuntimeInspectorMessage::from_renderer_message(message, Some(&target_id)), + ); } outputs } @@ -594,8 +556,8 @@ pub(in crate::domains) fn push_routed_renderer_runtime_inspector_message_batch_b Some(session_id) => CommandOwnerScope::for_session(session_id), None => CommandOwnerScope::capture(conn, None), }; - let prepared = RuntimePreparedOutputs::from_renderer_runtime_inspector_message_batches( - conn, &owner, &batches, + let prepared = RuntimePreparedOutputs::from_page_renderer_runtime_inspector_message_batches( + conn, &owner, batches, ); for batch in prepared .inspector_message_batches @@ -618,8 +580,8 @@ pub(in crate::domains) fn push_routed_renderer_runtime_inspector_message_batch_b #[cfg(test)] mod tests { use moli_core::page::{ - DevToolsSessionKey, RendererAgentAttachmentId, RendererDevToolsAgentToken, - RendererRuntimeInspectorMessage, RendererRuntimeInspectorMessageBatch, + DevToolsSessionKey, RendererAgentAttachmentId, RendererRuntimeInspectorMessage, + RendererRuntimeInspectorMessageBatch, }; use moli_page_types::RendererInspectorResponseDelivery; use serde_json::Value; @@ -732,20 +694,33 @@ mod tests { .map_or(DevToolsSessionKey::Primary, |session_id| { DevToolsSessionKey::Attached(session_id.to_owned()) }); + let agent_token = conn + .runtime_session_owner_slot_for_owner(&owner) + .expect("runtime owner slot") + .current_renderer_attachment() + .expect("current renderer attachment") + .agent_token(); let batches = vec![RendererRuntimeInspectorMessageBatch::new( - RendererDevToolsAgentToken::allocate(), + agent_token, session, renderer_messages(messages), )]; - RuntimePreparedOutputs::from_renderer_runtime_inspector_message_batches( - conn, &owner, &batches, + RuntimePreparedOutputs::from_page_renderer_runtime_inspector_message_batches( + conn, &owner, batches, ) } - #[test] - fn renderer_inspector_batches_keep_their_command_response_side() { - let (mut conn, _) = runtime_binding_attachment_fixture(); - let agent_token = RendererDevToolsAgentToken::allocate(); + #[tokio::test(flavor = "multi_thread")] + async fn renderer_inspector_batches_keep_their_command_response_side() { + let mut ctx = TestContext::new(); + load_document(&mut ctx, "
batch order
").await; + let agent_token = ctx + .conn + .runtime_session_owner_slot(Some("SID-1")) + .expect("runtime owner slot") + .current_renderer_attachment() + .expect("current renderer attachment") + .agent_token(); let session = DevToolsSessionKey::Primary; let batches = vec![ RendererRuntimeInspectorMessageBatch::new( @@ -766,10 +741,10 @@ mod tests { ), ]; - let outputs = RuntimePreparedOutputs::from_renderer_runtime_inspector_message_batches( - &mut conn, + let outputs = RuntimePreparedOutputs::from_page_renderer_runtime_inspector_message_batches( + &mut ctx.conn, &CommandOwnerScope::for_session("SID-1"), - &batches, + batches, ); assert_eq!(outputs.inspector_message_batches.len(), 1); @@ -857,12 +832,11 @@ mod tests { ); batch.bind_renderer_agent_attachment(retired_attachment); - let outputs = - RuntimePreparedOutputs::from_retired_renderer_runtime_inspector_session_responses( - &mut ctx.conn, - &CommandOwnerScope::for_session("SID-1"), - &[batch], - ); + let outputs = RuntimePreparedOutputs::from_page_renderer_runtime_inspector_message_batches( + &mut ctx.conn, + &CommandOwnerScope::for_session("SID-1"), + vec![batch], + ); let outputs_after_detach = outputs.clone(); let events = drain_runtime_inspector_outputs(&mut ctx.conn, outputs, None) .await @@ -1047,9 +1021,10 @@ mod tests { #[tokio::test(flavor = "multi_thread")] async fn runtime_inspector_activity_uses_capture_time_attachment() { - let (mut conn, _attachment) = runtime_binding_attachment_fixture(); + let mut ctx = TestContext::new(); + load_document(&mut ctx, "
capture
").await; let outputs = renderer_inspector_outputs( - &mut conn, + &mut ctx.conn, Some("SID-1"), None, vec![json!({ @@ -1062,7 +1037,8 @@ mod tests { })], ); let events = - drain_runtime_inspector_outputs(&mut conn, outputs, Some("SID-unrelated-drain")).await; + drain_runtime_inspector_outputs(&mut ctx.conn, outputs, Some("SID-unrelated-drain")) + .await; assert_eq!(events.len(), 1); let (message, automation_event) = events.into_iter().next().unwrap().into_parts(); @@ -1083,20 +1059,22 @@ mod tests { #[tokio::test(flavor = "multi_thread")] async fn runtime_inspector_activity_discards_replaced_page_output() { - let (mut conn, _attachment) = runtime_binding_attachment_fixture(); + let mut ctx = TestContext::new(); + load_document(&mut ctx, "
old
").await; let outputs = renderer_inspector_outputs( - &mut conn, + &mut ctx.conn, Some("SID-1"), None, vec![json!({ - "id": 91, - "result": { "value": "old-page-response" } + "method": "Debugger.scriptParsed", + "params": { "scriptId": "old-page" } })], ); - conn.runtime_session_owner_slot_mut(Some("SID-1")) + ctx.conn + .runtime_session_owner_slot_mut(Some("SID-1")) .expect("Runtime inspector target") .replace_page_attachment_id_for_test(); - let events = drain_runtime_inspector_outputs(&mut conn, outputs, Some("SID-1")).await; + let events = drain_runtime_inspector_outputs(&mut ctx.conn, outputs, Some("SID-1")).await; assert!( events.is_empty(), @@ -1106,9 +1084,10 @@ mod tests { #[tokio::test(flavor = "multi_thread")] async fn runtime_inspector_activity_discards_detached_attachment() { - let (mut conn, _attachment) = runtime_binding_attachment_fixture(); + let mut ctx = TestContext::new(); + load_document(&mut ctx, "
detach
").await; let outputs = renderer_inspector_outputs( - &mut conn, + &mut ctx.conn, Some("SID-1"), None, vec![json!({ @@ -1117,14 +1096,15 @@ mod tests { })], ); assert_eq!( - conn.browser_context + ctx.conn + .browser_context .as_mut() .expect("browser context") .detach_active_session() .as_deref(), Some("SID-1"), ); - let events = drain_runtime_inspector_outputs(&mut conn, outputs, None).await; + let events = drain_runtime_inspector_outputs(&mut ctx.conn, outputs, None).await; assert!( events.is_empty(), @@ -1133,73 +1113,76 @@ mod tests { } #[tokio::test(flavor = "multi_thread")] - async fn runtime_inspector_activity_preserves_auxiliary_renderer_route() { - let (mut conn, _attachment) = runtime_binding_attachment_fixture(); + async fn runtime_inspector_activity_preserves_attached_renderer_route() { + let mut ctx = TestContext::new(); + load_document(&mut ctx, "
attached
").await; assert!( - conn.browser_context + ctx.conn + .browser_context .as_mut() .expect("browser context") .assign_auxiliary_session_to_target("TID-1", "SID-aux".to_owned()) ); let outputs = renderer_inspector_outputs( - &mut conn, + &mut ctx.conn, Some("SID-1"), Some("SID-aux"), vec![json!({ - "id": 92, - "result": { "value": "auxiliary-response" } + "method": "Debugger.scriptParsed", + "params": { "scriptId": "attached-session" } })], ); - let events = drain_runtime_inspector_outputs(&mut conn, outputs, Some("SID-1")) + let events = drain_runtime_inspector_outputs(&mut ctx.conn, outputs, Some("SID-1")) .await .into_iter() .map(crate::conn::BackgroundProtocolEvent::into_protocol_message) .collect::>(); assert_eq!(events.len(), 1); - assert_eq!(events[0]["id"], json!(92)); + assert_eq!(events[0]["method"], json!("Debugger.scriptParsed")); assert_eq!( events[0]["sessionId"], json!("SID-aux"), - "an auxiliary renderer inspector batch must retain its own attachment instead of following the source or drain session" + "an attached renderer inspector batch must retain its own session instead of following the source or drain session" ); } #[tokio::test(flavor = "multi_thread")] async fn runtime_inspector_activity_authorizes_each_page_batch_independently() { - let (mut conn, _attachment) = runtime_binding_attachment_fixture(); + let mut ctx = TestContext::new(); + load_document(&mut ctx, "
first
").await; let mut outputs = renderer_inspector_outputs( - &mut conn, + &mut ctx.conn, Some("SID-1"), None, vec![json!({ - "id": 93, - "result": { "value": "old-page" } + "method": "Debugger.scriptParsed", + "params": { "scriptId": "old-page" } })], ); - conn.runtime_session_owner_slot_mut(Some("SID-1")) + ctx.conn + .runtime_session_owner_slot_mut(Some("SID-1")) .expect("Runtime inspector target") .replace_page_attachment_id_for_test(); outputs.extend(renderer_inspector_outputs( - &mut conn, + &mut ctx.conn, Some("SID-1"), None, vec![json!({ - "id": 94, - "result": { "value": "replacement-page" } + "method": "Debugger.scriptParsed", + "params": { "scriptId": "replacement-page" } })], )); let events = - drain_runtime_inspector_outputs(&mut conn, outputs, Some("SID-unrelated-drain")) + drain_runtime_inspector_outputs(&mut ctx.conn, outputs, Some("SID-unrelated-drain")) .await .into_iter() .map(crate::conn::BackgroundProtocolEvent::into_protocol_message) .collect::>(); assert_eq!(events.len(), 1); - assert_eq!(events[0]["id"], json!(94)); assert_eq!( - events[0]["result"]["value"], + events[0]["params"]["scriptId"], json!("replacement-page"), "one captured slot must validate each capture-time Page attachment instead of authorizing the whole slot from projection context" ); diff --git a/moli-protocol/src/domains/runtime/bindings.rs b/moli-protocol/src/domains/runtime/bindings.rs index ffe2d12580..a848280f1c 100644 --- a/moli-protocol/src/domains/runtime/bindings.rs +++ b/moli-protocol/src/domains/runtime/bindings.rs @@ -18,11 +18,9 @@ pub(super) fn persist_runtime_binding_definition_for_owner( name: String, execution_context_name: Option, ) -> Result<(), String> { - conn.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |state| state.upsert_runtime_binding_definition(name, execution_context_name), - ) + conn.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.upsert_runtime_binding_definition(name, execution_context_name) + }) .ok_or_else(|| "BrowserContextNotLoaded".to_owned()) } @@ -31,11 +29,9 @@ pub(super) fn remove_runtime_binding_definitions_for_owner( owner: &CommandOwnerScope, name: &str, ) -> Result<(), String> { - conn.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |state| state.remove_runtime_binding_definitions(name), - ) + conn.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.remove_runtime_binding_definitions(name) + }) .ok_or_else(|| "BrowserContextNotLoaded".to_owned()) } @@ -43,10 +39,8 @@ pub(super) fn clear_runtime_binding_definitions_for_owner( conn: &mut CdpConnection, owner: &CommandOwnerScope, ) -> Result<(), String> { - conn.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |state| state.clear_runtime_binding_definitions(), - ) + conn.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.clear_runtime_binding_definitions() + }) .ok_or_else(|| "BrowserContextNotLoaded".to_owned()) } diff --git a/moli-protocol/src/domains/runtime/dispatcher.rs b/moli-protocol/src/domains/runtime/dispatcher.rs index e4278a68ce..59e0db7c9b 100644 --- a/moli-protocol/src/domains/runtime/dispatcher.rs +++ b/moli-protocol/src/domains/runtime/dispatcher.rs @@ -480,6 +480,9 @@ struct RuntimeBindingCommandTask { execution_context_id: Option, inspector_json: Option, command_response: Option, + response_delivery: RendererInspectorResponseDelivery, + session_response_predecessor: Option, + session_response_succeeded: Option, should_persist: bool, skip_live_page_update_after_inspector_success: bool, } @@ -1026,11 +1029,7 @@ fn start_main_runtime_inspector_command_for_owner( cmd, &owner_scope, inspector_json, - if await_promise { - RendererInspectorResponseDelivery::CommandReply - } else { - cmd.terminal_response_delivery(RendererInspectorResponseDelivery::DevToolsSession) - }, + cmd.terminal_response_delivery(RendererInspectorResponseDelivery::DevToolsSession), ) { Ok(pending) => pending, Err(message) => { @@ -1179,7 +1178,7 @@ pub(crate) fn start_heap_profiler_inspector_command_dispatch( cmd, &owner_scope, cmd.json.to_owned(), - RendererInspectorResponseDelivery::CommandReply, + cmd.terminal_response_delivery(RendererInspectorResponseDelivery::DevToolsSession), ) { Ok(pending) => pending, Err(message) => { @@ -1656,10 +1655,7 @@ fn start_runtime_enable_command_for_owner( command_id: Option, owner_scope: CommandOwnerScope, ) -> RuntimeCommandTaskStep { - let has_loaded_page = match conn.runtime_session_owner_slot_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) { + let has_loaded_page = match conn.runtime_session_owner_slot_for_owner(&owner_scope) { Ok(slot) => slot.has_loaded_page(), Err(_) if owner_scope.session_id().is_some() => { return RuntimeCommandTaskStep::Complete(CommandOutputPlan::error( @@ -1729,7 +1725,7 @@ fn runtime_remove_binding_should_skip_live_page_update( conn: &CdpConnection, owner: &CommandOwnerScope, ) -> bool { - conn.target_runtime_session_state_for_route(owner.session_id(), owner.session_owner_route()) + conn.target_runtime_session_state_for_owner(owner) .is_some_and(|state| state.runtime_frontend_enabled) } @@ -1797,21 +1793,19 @@ fn try_start_pending_runtime_binding_command( execution_context_id, inspector_json: Some(cmd.json.to_owned()), command_response: None, + response_delivery: cmd + .terminal_response_delivery(RendererInspectorResponseDelivery::DevToolsSession), + session_response_predecessor: None, + session_response_succeeded: None, should_persist, skip_live_page_update_after_inspector_success: false, }; let live_page_update_unavailable = conn - .runtime_session_owner_slot_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) + .runtime_session_owner_slot_for_owner(&owner_scope) .is_ok_and(|slot| !slot.has_loaded_page()) || should_persist && conn - .runtime_session_owner_slot_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) + .runtime_session_owner_slot_for_owner(&owner_scope) .is_ok_and(|slot| slot.renderer_document_navigation_is_suspended()); if live_page_update_unavailable { task.command_response = Some(RuntimeBindingCommandResponse::empty_success()); @@ -1844,19 +1838,22 @@ fn try_start_pending_runtime_binding_command( } let action_label = action.label(); let pending = match action { - RuntimeBindingCommand::Add => start_pending_runtime_context_resolved_inspector_dispatch( - conn, - cmd, - &owner_scope, - action_label, - cmd.json.to_owned(), - ), + RuntimeBindingCommand::Add => { + start_pending_runtime_context_resolved_inspector_dispatch_with_delivery( + conn, + cmd, + &owner_scope, + action_label, + cmd.json.to_owned(), + task.response_delivery, + ) + } RuntimeBindingCommand::Remove => start_pending_runtime_inspector_dispatch_with_delivery( conn, cmd, &owner_scope, cmd.json.to_owned(), - RendererInspectorResponseDelivery::CommandReply, + task.response_delivery, ), }; let pending = match pending { @@ -1933,23 +1930,6 @@ fn start_pending_runtime_io_inspector_dispatch( } } -fn start_pending_runtime_context_resolved_inspector_dispatch( - conn: &mut CdpConnection, - cmd: &Cmd<'_>, - owner: &CommandOwnerScope, - action: &'static str, - inspector_json: String, -) -> Result { - start_pending_runtime_context_resolved_inspector_dispatch_with_delivery( - conn, - cmd, - owner, - action, - inspector_json, - RendererInspectorResponseDelivery::CommandReply, - ) -} - fn start_pending_runtime_context_resolved_inspector_dispatch_with_delivery( conn: &mut CdpConnection, cmd: &Cmd<'_>, @@ -2089,11 +2069,7 @@ fn start_cdp_devtools_script_runtime_command( command, inspector_json, await_promise, - if await_promise { - RendererInspectorResponseDelivery::CommandReply - } else { - cmd.terminal_response_delivery(RendererInspectorResponseDelivery::DevToolsSession) - }, + cmd.terminal_response_delivery(RendererInspectorResponseDelivery::DevToolsSession), ) } @@ -4219,26 +4195,19 @@ pub(crate) async fn start_bidi_preload_channel_listeners_for_execution_context_b out: &mut Vec, ) { let session_id = owner.session_id(); - let handoff_owners = conn.target_owner_bidi_channel_preload_handoffs_for_route( - session_id, - owner.session_owner_route(), - ); + let handoff_owners = conn.target_owner_bidi_channel_preload_handoffs_for_owner(owner); if handoff_owners.is_empty() { return; } let target_id = conn - .target_owner_identity_for_route(session_id, owner.session_owner_route()) + .target_owner_identity_for_owner(owner) .and_then(|(_, target_id)| target_id) .map(DevToolsTargetId::from); - let route = owner - .session_owner_route() - .cloned() - .or_else(|| conn.session_route(session_id)) - .or_else(|| { - target_id - .as_ref() - .and_then(|target_id| conn.target_session_route_for_target_id(target_id.as_str())) - }); + let route = owner.resolve_route(conn).or_else(|| { + target_id + .as_ref() + .and_then(|target_id| conn.target_session_route_for_target_id(target_id.as_str())) + }); let Some(route) = route else { return; }; @@ -7681,7 +7650,7 @@ fn start_pending_runtime_binding_inspector_phase( let descriptor = RendererCommandDescriptor::from_frontend_policy( inspector_json, task.renderer_policy, - RendererInspectorResponseDelivery::CommandReply, + task.response_delivery, ); conn.start_runtime_protocol_message_with_context_resolution_for_owner_with_deferred_response( &completed.owner_scope, @@ -7702,7 +7671,7 @@ fn start_pending_runtime_binding_inspector_phase( let descriptor = RendererCommandDescriptor::from_frontend_policy( inspector_json, task.renderer_policy, - RendererInspectorResponseDelivery::CommandReply, + task.response_delivery, ); conn.start_runtime_protocol_message_for_owner_with_deferred_response( &completed.owner_scope, @@ -7819,7 +7788,7 @@ fn prepare_runtime_inspector_payload_for_owner( } RuntimeInspectorPayloadPreparation::PrepareCallFunctionOn => { let (browser_context_id, target_id) = conn - .target_owner_identity_for_route(owner.session_id(), owner.session_owner_route()) + .target_owner_identity_for_owner(owner) .map(|(browser_context_id, target_id)| (Some(browser_context_id), target_id)) .unwrap_or((None, None)); let command = build_cdp_call_function_command( @@ -8320,12 +8289,8 @@ async fn complete_pending_runtime_inspector_command( if !saw_current_response && renderer_response_rx.is_some() && completed.command_id.is_some_and(|command_id| { - conn.renderer_runtime_command_cause_for_route( - completed.session_id(), - completed.owner_scope.session_owner_route(), - command_id, - ) - .is_none() + conn.renderer_runtime_command_cause_for_owner(&completed.owner_scope, command_id) + .is_none() }) { renderer_response_rx.take(); @@ -8359,7 +8324,8 @@ async fn complete_pending_runtime_inspector_command( saw_current_response, ); } - if completed.wait_for_deferred_reply + if response_delivery == RendererInspectorResponseDelivery::CommandReply + && completed.wait_for_deferred_reply && (renderer_response_rx.is_some() || !saw_current_response) && completed.command_id.is_some() { @@ -8571,10 +8537,7 @@ fn complete_pending_runtime_enable_command( { return CommandOutputPlan::error(-32000, message); } - let frame_id = conn.runtime_session_owner_frame_id_for_route( - completed.owner_scope.session_id(), - completed.owner_scope.session_owner_route(), - ); + let frame_id = conn.runtime_session_owner_frame_id_for_owner(&completed.owner_scope); let mut plan = CommandOutputPlan::success(); for event in replay.into_events() { @@ -8682,19 +8645,50 @@ async fn complete_pending_runtime_binding_inspector_command( completed_inspector: Result, response_flush: &crate::conn::CommandResponseFlushContext, ) -> RuntimeCommandTaskStep { - let (messages, mut renderer_response_rx) = match completed_inspector { + let ( + messages, + mut renderer_response_rx, + response_delivery, + session_response_predecessor, + session_response_succeeded, + ) = match completed_inspector { Ok(mut completed_protocol) => { + let response_delivery = completed_protocol.response_delivery(); + let session_response_predecessor = completed_protocol.session_response_predecessor(); + let session_response_succeeded = completed_protocol.session_response_succeeded(); let renderer_response_rx = completed_protocol.take_deferred_response_receiver(); match conn .complete_runtime_protocol_message_async(completed_protocol) .await { - Ok(messages) => (messages, renderer_response_rx), + Ok(messages) => ( + messages, + renderer_response_rx, + response_delivery, + session_response_predecessor, + session_response_succeeded, + ), Err(message) => { - return RuntimeCommandTaskStep::Complete(runtime_inspector_error_plan( - completed.command_id, - message, - )); + if session_response_succeeded.is_some() { + tracing::warn!( + command_id = completed.command_id, + session_id = completed.session_id(), + error = %message, + "could not apply Runtime binding browser projection after the renderer session settled the terminal response" + ); + ( + None, + renderer_response_rx, + response_delivery, + session_response_predecessor, + session_response_succeeded, + ) + } else { + return RuntimeCommandTaskStep::Complete(runtime_inspector_error_plan( + completed.command_id, + message, + )); + } } } } @@ -8705,6 +8699,11 @@ async fn complete_pending_runtime_binding_inspector_command( )); } }; + debug_assert_eq!(response_delivery, task.response_delivery); + if let Some(predecessor) = session_response_predecessor { + predecessor.merge_into_same_stream_tail(&mut task.session_response_predecessor); + } + task.session_response_succeeded = session_response_succeeded; let mut routed_output = RuntimeInspectorRoutedOutput::default(); let saw_current_response = if let Some(messages) = messages { route_renderer_command_turn_output_into_routed_output( @@ -8722,7 +8721,12 @@ async fn complete_pending_runtime_binding_inspector_command( if saw_current_response { renderer_response_rx.take(); } - if let Some(renderer_response_rx) = renderer_response_rx { + if response_delivery == RendererInspectorResponseDelivery::DevToolsSession { + renderer_response_rx.take(); + } + if response_delivery == RendererInspectorResponseDelivery::CommandReply + && let Some(renderer_response_rx) = renderer_response_rx + { route_registered_runtime_response_receiver_into( conn, completed.command_id, @@ -8732,11 +8736,13 @@ async fn complete_pending_runtime_binding_inspector_command( ) .await; } - record_runtime_binding_command_response_from_routed_events( - &mut task, - routed_output.events(), - completed.command_id, - ); + if response_delivery == RendererInspectorResponseDelivery::CommandReply { + record_runtime_binding_command_response_from_routed_events( + &mut task, + routed_output.events(), + completed.command_id, + ); + } if routed_output.background_event_count() > 0 { tracing::debug!( events = routed_output.background_event_count(), @@ -8838,6 +8844,12 @@ fn complete_runtime_binding_after_live_update( fn runtime_binding_output_plan(task: RuntimeBindingCommandTask) -> CommandOutputPlan { let mut plan = CommandOutputPlan::default(); + if let Some(predecessor) = task.session_response_predecessor { + plan.set_renderer_output_predecessor(predecessor); + } + if task.session_response_succeeded.is_some() { + return plan; + } match task.command_response { Some(response) => response.push_into_plan(&mut plan), None => plan.push_error(-32000, "MissingRuntimeBindingCommandResponse"), @@ -8888,6 +8900,9 @@ fn record_runtime_binding_command_response_from_routed_events( } fn runtime_binding_command_response_succeeded(task: &RuntimeBindingCommandTask) -> bool { + if let Some(succeeded) = task.session_response_succeeded { + return succeeded; + } task.command_response .as_ref() .is_some_and(RuntimeBindingCommandResponse::succeeded) @@ -9221,11 +9236,8 @@ fn start_pending_shared_worker_runtime_inspector_command( action.label(), ) .map_err(|error| error.to_string())?; - let response_delivery = if await_promise { - RendererInspectorResponseDelivery::CommandReply - } else { - cmd.terminal_response_delivery(RendererInspectorResponseDelivery::DevToolsSession) - }; + let response_delivery = + cmd.terminal_response_delivery(RendererInspectorResponseDelivery::DevToolsSession); let pending = match start_shared_worker_frontend_inspector_dispatch( conn, cmd, @@ -9293,11 +9305,8 @@ fn start_pending_service_worker_runtime_inspector_command( action.label(), ) .map_err(|error| error.to_string())?; - let response_delivery = if await_promise { - RendererInspectorResponseDelivery::CommandReply - } else { - cmd.terminal_response_delivery(RendererInspectorResponseDelivery::DevToolsSession) - }; + let response_delivery = + cmd.terminal_response_delivery(RendererInspectorResponseDelivery::DevToolsSession); let pending = match start_service_worker_frontend_inspector_dispatch( conn, cmd, @@ -9465,6 +9474,12 @@ async fn complete_pending_shared_worker_runtime_inspector_command( ) = match completed_inspector { Ok(mut completed_protocol) => { let response_delivery = completed_protocol.response_delivery(); + if response_delivery == RendererInspectorResponseDelivery::DevToolsSession + && !completed.await_promise + && let Err(message) = completed_protocol.wait_for_session_response().await + { + return complete_shared_worker_runtime_inspector_error(conn, completed, message); + } let session_response_predecessor = completed_protocol.session_response_predecessor(); let session_response_succeeded = completed_protocol.session_response_succeeded(); let renderer_response_rx = completed_protocol.take_deferred_response_receiver(); @@ -9543,6 +9558,18 @@ async fn complete_pending_shared_worker_runtime_inspector_command( renderer_response_rx, ); } + if response_delivery == RendererInspectorResponseDelivery::DevToolsSession + && completed.await_promise + && session_response_succeeded.is_none() + { + // The Worker accepted an asynchronous Inspector command. Its terminal + // response now belongs exclusively to the Worker target journal and + // may arrive on a later turn; releasing this command here lets the + // same or another DevTools session continue driving the worker. + routed_output + .push_background_events_before_response_events(&mut plan, completed.command_id); + return RuntimeCommandTaskStep::Complete(plan); + } let succeeded = session_response_succeeded .unwrap_or_else(|| routed_output.command_response_succeeded(completed.command_id)); apply_shared_worker_runtime_completion_projection( @@ -9636,6 +9663,12 @@ async fn complete_pending_service_worker_runtime_inspector_command( ) = match completed_inspector { Ok(mut completed_protocol) => { let response_delivery = completed_protocol.response_delivery(); + if response_delivery == RendererInspectorResponseDelivery::DevToolsSession + && !completed.await_promise + && let Err(message) = completed_protocol.wait_for_session_response().await + { + return complete_service_worker_runtime_inspector_error(conn, completed, message); + } let session_response_predecessor = completed_protocol.session_response_predecessor(); let session_response_succeeded = completed_protocol.session_response_succeeded(); let renderer_response_rx = completed_protocol.take_deferred_response_receiver(); @@ -9714,6 +9747,14 @@ async fn complete_pending_service_worker_runtime_inspector_command( renderer_response_rx, ); } + if response_delivery == RendererInspectorResponseDelivery::DevToolsSession + && completed.await_promise + && session_response_succeeded.is_none() + { + routed_output + .push_background_events_before_response_events(&mut plan, completed.command_id); + return RuntimeCommandTaskStep::Complete(plan); + } let succeeded = session_response_succeeded .unwrap_or_else(|| routed_output.command_response_succeeded(completed.command_id)); apply_service_worker_runtime_completion_projection( @@ -10346,10 +10387,7 @@ fn start_runtime_disable_command_for_owner( response_delivery: RendererInspectorResponseDelivery, ) -> RuntimeCommandTaskStep { if !conn - .runtime_session_owner_slot_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) + .runtime_session_owner_slot_for_owner(&owner_scope) .is_ok_and(|slot| slot.has_loaded_page()) { return RuntimeCommandTaskStep::Complete(disable_command_output_plan_sync_for_owner( @@ -10460,7 +10498,7 @@ fn apply_runtime_disable_projection_after_success_for_owner( owner: &CommandOwnerScope, ) -> Result<(), String> { let was_enabled = conn - .target_runtime_session_state_for_route(owner.session_id(), owner.session_owner_route()) + .target_runtime_session_state_for_owner(owner) .is_some_and(|state| state.runtime_frontend_enabled); match conn.set_runtime_frontend_enabled_for_owner(owner, false) { SessionOwnerRuntimeFrontendEnableResult::Handled => { diff --git a/moli-protocol/src/domains/runtime/tests/evaluate.rs b/moli-protocol/src/domains/runtime/tests/evaluate.rs index 75c88e0be2..58b44fc1c7 100644 --- a/moli-protocol/src/domains/runtime/tests/evaluate.rs +++ b/moli-protocol/src/domains/runtime/tests/evaluate.rs @@ -2448,7 +2448,9 @@ async fn page_navigate_network_failure_commits_error_document() { ); let error_document_loader_id = ctx .conn - .target_session_owner_frame_tree_loader_id_for_route(Some("SID-1"), None) + .target_session_owner_frame_tree_loader_id_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1"), + ) .expect("error Document loader id"); let stale_request_id = "REQ-before-network-error"; let stale_body_completion = BackgroundNavigationCompletion::main_document_body( @@ -2492,7 +2494,9 @@ async fn page_navigate_network_failure_commits_error_document() { assert!(stale_completion_scheduler_events.is_empty()); assert_eq!( ctx.conn - .target_session_owner_frame_tree_loader_id_for_route(Some("SID-1"), None) + .target_session_owner_frame_tree_loader_id_for_owner( + &crate::conn::CommandOwnerScope::for_session("SID-1") + ) .as_deref(), Some(error_document_loader_id.as_str()), "stale body completion must not replace the error Document loader" @@ -2838,7 +2842,7 @@ async fn evaluate_await_promise_scheduler_routed_reply_clears_pending_await_regi } #[tokio::test] -async fn runtime_await_promise_pending_registers_renderer_response_receiver() { +async fn runtime_await_promise_releases_dispatch_before_session_response() { let mut ctx = TestContext::new(); with_loaded_document_async(&mut ctx, "ok").await; @@ -2868,50 +2872,45 @@ async fn runtime_await_promise_pending_registers_renderer_response_receiver() { .conn .try_start_pending_command_dispatch(&raw) .expect("Runtime.awaitPromise should start as a pending command"); - let (mut pending, scheduler_events) = match ctx - .conn - .complete_pending_command_dispatch(pending.wait().await) + let completed = tokio::time::timeout(std::time::Duration::from_secs(1), pending.wait()) .await - { - CdpCommandTaskStep::Pending(pending) => (*pending, ctx.conn.take_scheduler_events()), - CdpCommandTaskStep::Complete(outcome) => { - panic!( - "never-settling Runtime.awaitPromise should stay pending after initial inspector dispatch: {:?}", - outcome.into_parts().0 - ); - } + .expect("initial Page Inspector dispatch must not wait for Promise settlement"); + let CdpCommandTaskStep::Complete(outcome) = + ctx.conn.complete_pending_command_dispatch(completed).await + else { + panic!("a Page session response must not enter the CommandReply deferred-reply lane"); }; + drop(outcome); assert!( - scheduler_events.is_empty(), - "pending Runtime.awaitPromise must wait on its inspector response receiver, not scheduler follow-up work: {scheduler_events:?}" + ctx.conn.take_scheduler_events().is_empty(), + "an unresolved session response must not manufacture scheduler follow-up work" ); assert!( - pending.waits_for_scheduler_deferred_inspector_reply(), - "Runtime.awaitPromise should enter scheduler deferred-reply state" + ctx.conn + .has_pending_inspector_awaits_for_session_owner(None), + "the unresolved await must remain registered to its exact Page session" ); assert!( ctx.conn - .has_pending_inspector_awaits_for_session_owner(None), - "scheduler-deferred Runtime.awaitPromise should remain visible as pending command-owned work" + .has_unclaimed_pending_inspector_awaits_for_session_owner(None), + "the session output path must leave the await under renderer ownership" ); assert!( !ctx.conn - .has_unclaimed_pending_inspector_awaits_for_session_owner(None), - "scheduler-deferred Runtime.awaitPromise should claim the pending await out of the document registry" - ); - assert!( - ctx.conn .has_claimed_pending_inspector_awaits_for_session_owner(None), - "scheduler-deferred Runtime.awaitPromise should be tracked by the command-owned await index" + "the CommandReply claimed-await index must remain unused" ); - assert!( - pending - .take_scheduler_deferred_inspector_reply_receiver() - .is_some(), - "pending Runtime.awaitPromise should own the renderer response receiver" + + ctx.process_async(json!({ + "id": 3_024, + "method": "Page.close" + })) + .await; + assert_eq!( + take_response_by_id(&mut ctx, 3_023)["error"]["message"], + json!("Page closed") ); - pending.forget_scheduler_deferred_inspector_reply(&mut ctx.conn); } #[tokio::test] diff --git a/moli-protocol/src/domains/runtime/tests/shared_worker.rs b/moli-protocol/src/domains/runtime/tests/shared_worker.rs index e65107cbb3..2caf9555f0 100644 --- a/moli-protocol/src/domains/runtime/tests/shared_worker.rs +++ b/moli-protocol/src/domains/runtime/tests/shared_worker.rs @@ -3399,7 +3399,7 @@ async fn shared_worker_await_promise_timer_reply_arrives_through_renderer_receiv } #[tokio::test(flavor = "multi_thread")] -async fn shared_worker_await_promise_pending_registers_renderer_response_receiver() { +async fn shared_worker_await_promise_releases_dispatch_before_session_response() { let mut ctx = TestContext::new(); with_loaded_document_async(&mut ctx, "").await; let shared_worker_session_id = start_attached_shared_worker_session( @@ -3429,31 +3429,33 @@ onconnect = event => { .conn .try_start_pending_command_dispatch(&raw) .expect("shared worker Runtime.evaluate awaitPromise should start as a pending command"); - let mut pending = match ctx - .conn - .complete_pending_command_dispatch(pending.wait().await) + let completed = tokio::time::timeout(std::time::Duration::from_secs(1), pending.wait()) .await - { - CdpCommandTaskStep::Pending(pending) => *pending, - CdpCommandTaskStep::Complete(outcome) => { - panic!( - "shared worker Runtime.evaluate awaitPromise should stay pending after initial inspector dispatch: {:?}", - outcome.into_parts().0 - ); - } + .expect("initial Worker Inspector dispatch must not wait for Promise settlement"); + let CdpCommandTaskStep::Complete(outcome) = + ctx.conn.complete_pending_command_dispatch(completed).await + else { + panic!("a Worker session response must not enter the CommandReply deferred-reply lane"); }; + assert!( + outcome.into_parts().0.is_empty(), + "the unresolved terminal response must remain in the Worker session output journal" + ); + assert!( + ctx.conn + .has_pending_inspector_awaits_for_session_owner(Some(&shared_worker_session_id)), + "the unresolved await must remain registered to its exact Worker session" + ); - assert!( - pending.waits_for_scheduler_deferred_inspector_reply(), - "awaitPromise should enter scheduler deferred-reply state" - ); - assert!( - pending - .take_scheduler_deferred_inspector_reply_receiver() - .is_some(), - "shared worker awaitPromise should own the renderer response receiver" - ); - pending.forget_scheduler_deferred_inspector_reply(&mut ctx.conn); + ctx.process_async(json!({ + "id": 91_103, + "method": "Target.detachFromTarget", + "params": { "sessionId": shared_worker_session_id } + })) + .await; + assert_eq!(take_response_by_id(&mut ctx, 91_103)["result"], json!({})); + let failed_await = take_response_by_id(&mut ctx, 91_102); + assert_eq!(failed_await["error"]["message"], json!("Target detached")); } #[tokio::test(flavor = "multi_thread")] diff --git a/moli-protocol/src/domains/runtime_context_events.rs b/moli-protocol/src/domains/runtime_context_events.rs index 7765112b47..bd5d94781c 100644 --- a/moli-protocol/src/domains/runtime_context_events.rs +++ b/moli-protocol/src/domains/runtime_context_events.rs @@ -295,9 +295,7 @@ pub(crate) fn qualify_runtime_context_protocol_event_for_owner_typed( ); return; } - let Some((_, Some(target_id))) = - conn.target_owner_identity_for_route(owner.session_id(), owner.session_owner_route()) - else { + let Some((_, Some(target_id))) = conn.target_owner_identity_for_owner(owner) else { return; }; match event { @@ -422,18 +420,16 @@ pub(crate) fn should_emit_child_default_context_inventory_replay_once_for_owner( return true; } if conn - .target_devtools_session_state_for_route(owner.session_id(), owner.session_owner_route()) + .target_devtools_session_state_for_owner(owner) .is_some_and(|state| { state.has_emitted_child_default_execution_context_id(execution_context_id) }) { return false; } - let _ = conn.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |state| state.mark_child_default_execution_context_id_emitted(execution_context_id), - ); + let _ = conn.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.mark_child_default_execution_context_id_emitted(execution_context_id) + }); true } @@ -473,9 +469,7 @@ fn record_child_default_context_delivery_for_owner( let Some(execution_context_id) = child_default_execution_context_id(event) else { return; }; - let Some(root_frame_id) = conn - .runtime_session_owner_frame_id_for_route(owner.session_id(), owner.session_owner_route()) - else { + let Some(root_frame_id) = conn.runtime_session_owner_frame_id_for_owner(owner) else { return; }; if event @@ -485,11 +479,9 @@ fn record_child_default_context_delivery_for_owner( { return; } - let _ = conn.with_target_devtools_session_state_for_route_mut( - owner.session_id(), - owner.session_owner_route(), - |state| state.mark_child_default_execution_context_id_emitted(execution_context_id), - ); + let _ = conn.with_target_devtools_session_state_for_owner_mut(owner, |state| { + state.mark_child_default_execution_context_id_emitted(execution_context_id) + }); } fn mark_child_default_context_event_emitted( diff --git a/moli-protocol/src/domains/security.rs b/moli-protocol/src/domains/security.rs index afd3a05235..046a75816e 100644 --- a/moli-protocol/src/domains/security.rs +++ b/moli-protocol/src/domains/security.rs @@ -97,11 +97,7 @@ pub(crate) fn complete_pending_security_command( Err(error) => return CommandOutputPlan::error(-32000, error), }; let owner_scope = completed.owner_scope; - match conn.finish_rebuild_resource_runtime_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - completion, - ) { + match conn.finish_rebuild_resource_runtime_for_owner(&owner_scope, completion) { Ok(()) => CommandOutputPlan::success(), Err(error) => CommandOutputPlan::error(-32000, error), } diff --git a/moli-protocol/src/domains/storage/ops.rs b/moli-protocol/src/domains/storage/ops.rs index 80594df17d..afeb2cabb3 100644 --- a/moli-protocol/src/domains/storage/ops.rs +++ b/moli-protocol/src/domains/storage/ops.rs @@ -479,19 +479,11 @@ fn start_get_storage_key_for_frame_command( }; let owner_scope = CommandOwnerScope::capture(conn, cmd.session_id); - let Some((target_id, target_url, _, _)) = conn - .target_session_owner_frame_tree_identity_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) + let Some((target_id, target_url, _, _)) = + conn.target_session_owner_frame_tree_identity_for_owner(&owner_scope) else { let plan = if conn.browser_context.is_none() - && conn - .target_owner_identity_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) - .is_none() + && conn.target_owner_identity_for_owner(&owner_scope).is_none() { CommandOutputPlan::error(-31998, "BrowserContextNotLoaded") } else { @@ -501,9 +493,7 @@ fn start_get_storage_key_for_frame_command( }; if params.frame_id == target_id { - if let Some(page) = - loaded_page_mut_for_session(conn, cmd.session_id, owner_scope.session_owner_route()) - { + if let Some(page) = loaded_page_mut_for_owner(conn, &owner_scope) { return match page.start_document_storage_key_snapshot() { Ok(pending) => StorageCommandTaskStep::Pending(PendingStorageCommandDispatch { command_id: cmd.id, @@ -526,15 +516,10 @@ fn start_get_storage_key_for_frame_command( )); } - if let Err(message) = conn.ensure_document_accessible_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) { + if let Err(message) = conn.ensure_document_accessible_for_owner(&owner_scope) { return StorageCommandTaskStep::Complete(CommandOutputPlan::error(-32000, message)); } - let Some(page) = - loaded_page_mut_for_session(conn, cmd.session_id, owner_scope.session_owner_route()) - else { + let Some(page) = loaded_page_mut_for_owner(conn, &owner_scope) else { return StorageCommandTaskStep::Complete(CommandOutputPlan::error( -32000, "NoFrameForGivenId", @@ -782,11 +767,7 @@ fn complete_get_storage_key_for_top_frame_command( Ok(completion) => completion, Err(error) => return CommandOutputPlan::error(-32000, error), }; - let Some(page) = loaded_page_mut_for_session( - conn, - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) else { + let Some(page) = loaded_page_mut_for_owner(conn, owner_scope) else { return CommandOutputPlan::error(-32000, "NoFrameForGivenId"); }; match page.finish_document_storage_key_snapshot(completion) { @@ -805,11 +786,7 @@ fn complete_get_storage_key_for_frame_command( Ok(completion) => completion, Err(error) => return CommandOutputPlan::error(-32000, error), }; - let Some(page) = loaded_page_mut_for_session( - conn, - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) else { + let Some(page) = loaded_page_mut_for_owner(conn, owner_scope) else { return CommandOutputPlan::error(-32000, "NoFrameForGivenId"); }; let child_frames = match page.finish_child_frame_tree_snapshot(completion) { @@ -920,12 +897,11 @@ fn complete_set_cookies_result( Ok(set_cookie_reports_result(&reports)) } -fn loaded_page_mut_for_session<'a>( +fn loaded_page_mut_for_owner<'a>( conn: &'a mut CdpConnection, - session_id: Option<&str>, - owner_route: Option<&crate::conn::CdpSessionRoute>, + owner: &CommandOwnerScope, ) -> Option<&'a mut moli_core::page::Page> { - conn.loaded_page_mut_for_protocol_access_for_route(session_id, owner_route) + conn.loaded_page_mut_for_protocol_access_for_owner(owner) .ok() } diff --git a/moli-protocol/src/domains/target.rs b/moli-protocol/src/domains/target.rs index f05acf7932..08ebe7ce0d 100644 --- a/moli-protocol/src/domains/target.rs +++ b/moli-protocol/src/domains/target.rs @@ -1,7 +1,8 @@ use serde::Deserialize; use crate::conn::{ - BackgroundProtocolEvent, BrowserContext, CdpConnection, Cmd, TargetHandlerAccessMode, + BackgroundProtocolEvent, BrowserContext, CdpConnection, Cmd, CommandOwnerScope, + TargetHandlerAccessMode, }; use crate::devtools_runtime::{ DevToolsActivateTargetCommand, DevToolsCloseTargetCommand, DevToolsCommand, @@ -35,19 +36,16 @@ pub(crate) use popup::{ PopupTargetCreation, PopupTargetOpenerIdentity, complete_popup_target_activation_action_async, complete_popup_target_navigation_owner_action_async, create_popup_target_from_renderer_output_background_events_async, - emit_target_info_changed_for_session_owner_background_event, + emit_target_info_changed_for_owner_background_event, schedule_initial_document_target_url_navigation_after_debugger_barrier_release_for_target, schedule_initial_document_target_url_navigation_after_debugger_resume, }; -pub(crate) fn popup_activation_creates_new_target_for_route( +pub(crate) fn popup_activation_creates_new_target_for_owner( conn: &CdpConnection, - owner_session_id: Option<&str>, - owner_route: Option<&crate::conn::CdpSessionRoute>, + owner: &CommandOwnerScope, target_name: &str, ) -> bool { - if let Some((browser_context_id, _)) = - conn.target_owner_identity_for_route(owner_session_id, owner_route) - { + if let Some((browser_context_id, _)) = conn.target_owner_identity_for_owner(owner) { return conn .browser_context_by_id(&browser_context_id) .is_none_or(|browser_context| { diff --git a/moli-protocol/src/domains/target/popup.rs b/moli-protocol/src/domains/target/popup.rs index 698d8a2b0c..78341e171d 100644 --- a/moli-protocol/src/domains/target/popup.rs +++ b/moli-protocol/src/domains/target/popup.rs @@ -503,10 +503,7 @@ pub(crate) async fn complete_popup_target_navigation_owner_action_async( ) -> crate::conn::CdpTurnOutcome { let (owner_scope, browser_context_id, target_id, url, kind) = action.into_parts(); let target_is_current = conn - .target_owner_identity_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) + .target_owner_identity_for_owner(&owner_scope) .is_some_and(|(current_browser_context_id, current_target_id)| { current_browser_context_id == browser_context_id && current_target_id.as_deref() == Some(target_id.as_str()) @@ -578,15 +575,13 @@ pub(crate) async fn complete_popup_target_activation_action_async( action: PopupTargetActivationAction, ) -> crate::conn::CdpTurnOutcome { let (owner_scope, browser_context_id, target_id) = action.into_parts(); - let target_is_current = - conn.target_owner_identity_for_route( - owner_scope.session_id(), - owner_scope.session_owner_route(), - ) + let target_is_current = conn + .target_owner_identity_for_owner(&owner_scope) .is_some_and(|(current_browser_context_id, current_target_id)| { current_browser_context_id == browser_context_id && current_target_id.as_deref() == Some(target_id.as_str()) - }) && popup_target_has_loaded_page(conn, &browser_context_id, &target_id); + }) + && popup_target_has_loaded_page(conn, &browser_context_id, &target_id); if !target_is_current { tracing::debug!( browser_context_id, @@ -651,12 +646,12 @@ async fn activate_popup_target_async( result } -pub(crate) fn emit_target_info_changed_for_session_owner_background_event( +pub(crate) fn emit_target_info_changed_for_owner_background_event( conn: &mut CdpConnection, out: &mut Vec, - session_id: Option<&str>, + owner: &CommandOwnerScope, ) { - out.extend(conn.target_info_changed_event_plan_for_session_owner(session_id)); + out.extend(conn.target_info_changed_event_plan_for_owner(owner)); } fn emit_target_info_changed_for_target_background_event( diff --git a/moli-protocol/src/domains/target/tests/tests_cdp_smoke_playwright.rs b/moli-protocol/src/domains/target/tests/tests_cdp_smoke_playwright.rs index 321cd9d922..cac82b1bdc 100644 --- a/moli-protocol/src/domains/target/tests/tests_cdp_smoke_playwright.rs +++ b/moli-protocol/src/domains/target/tests/tests_cdp_smoke_playwright.rs @@ -134,7 +134,9 @@ async fn arm_popup_route( ctx.expect_result(base + 2, json!({}), Some(popup_session_id)); let fetch_snapshot = ctx .conn - .target_fetch_subresource_interception_snapshot_for_route(Some(popup_session_id), None) + .target_fetch_subresource_interception_snapshot_for_owner( + &crate::conn::CommandOwnerScope::for_session(popup_session_id), + ) .expect("popup target Fetch configuration"); let matching_sessions = fetch_snapshot.matching_request_stage_pause_sessions( Some(popup_session_id), diff --git a/moli-protocol/src/domains/target/tests/tests_target_attachment.rs b/moli-protocol/src/domains/target/tests/tests_target_attachment.rs index cb81cb61e3..a6058706b1 100644 --- a/moli-protocol/src/domains/target/tests/tests_target_attachment.rs +++ b/moli-protocol/src/domains/target/tests/tests_target_attachment.rs @@ -1343,18 +1343,12 @@ async fn session_route_finds_browser_active_auxiliary_background_and_inactive_se ); assert_eq!(ctx.conn.session_route(Some("SID-missing")), None); assert_eq!( - ctx.conn - .background_target_id_for_session(Some("SID-inactive-background")), - Some("TID-000000000D".to_owned()) - ); - assert_eq!( - ctx.conn - .background_target_id_for_session(Some("SID-inactive-aux-background")), - Some("TID-000000000D".to_owned()) - ); - assert!( - ctx.conn - .has_background_target_session(Some("SID-inactive-background")) + ctx.conn.session_route(Some("SID-inactive-background")), + Some(CdpSessionRoute::PageTarget { + browser_context_id: "BID-B".to_owned(), + target_id: "TID-000000000D".to_owned(), + session_key: moli_page_types::DevToolsSessionKey::Primary, + }) ); assert_eq!( ctx.conn.session_route(Some("SID-inactive-aux-background")), @@ -1373,39 +1367,28 @@ async fn session_route_finds_browser_active_auxiliary_background_and_inactive_se target_id: "TID-shared-inactive".to_owned(), }) ); - assert_eq!( - ctx.conn.with_background_target_session( - Some("SID-inactive-background"), - |bc, target_id| { - assert_eq!(bc.id, "BID-B"); - bc.background_target_mut(target_id) - .expect("background target must exist") - .devtools_sessions[moli_page_types::DevToolsSessionKey::Primary] - .console_output_session_state - .console_enabled = true; - target_id.to_owned() - } - ), - Some("TID-000000000D".to_owned()) - ); + ctx.conn + .browser_context_by_id_mut("BID-B") + .expect("inactive browser context") + .page_target_mut("TID-000000000D") + .expect("stable page target") + .devtools_sessions[moli_page_types::DevToolsSessionKey::Primary] + .console_output_session_state + .console_enabled = true; assert_eq!( ctx.conn.browser_context.as_ref().map(|bc| bc.id.as_str()), Some("BID-A"), "direct background route helpers must not promote inactive browser contexts" ); - assert_eq!( - ctx.conn.with_background_target_session( - Some("SID-inactive-background"), - |bc, target_id| { - assert_eq!(bc.id, "BID-B"); - bc.background_target(target_id) - .expect("background target must exist") - .devtools_sessions[moli_page_types::DevToolsSessionKey::Primary] - .console_output_session_state - .console_enabled - } - ), - Some(true) + assert!( + ctx.conn + .browser_context_by_id("BID-B") + .expect("inactive browser context") + .page_target("TID-000000000D") + .expect("stable page target") + .devtools_sessions[moli_page_types::DevToolsSessionKey::Primary] + .console_output_session_state + .console_enabled ); assert!( diff --git a/moli-protocol/src/domains/target/worker_target.rs b/moli-protocol/src/domains/target/worker_target.rs index 9c4ed1534a..ffa219559c 100644 --- a/moli-protocol/src/domains/target/worker_target.rs +++ b/moli-protocol/src/domains/target/worker_target.rs @@ -431,20 +431,14 @@ pub(in crate::domains) fn dedicated_worker_target_lifecycle_prepared_outputs_for owner: &CommandOwnerScope, event: RendererDedicatedWorkerTargetEvent, ) -> TargetPreparedOutputs { - let session_id = owner.session_id(); - let owner_route = owner.session_owner_route(); - let Some(owner_page) = conn.target_page_residence_identity_for_route(session_id, owner_route) - else { + let Some(owner_page) = conn.target_page_residence_identity_for_owner(owner) else { return TargetPreparedOutputs::default(); }; - let Some(owner_renderer_page) = - conn.renderer_page_residence_identity_for_route(session_id, owner_route) - else { + let Some(owner_renderer_page) = conn.renderer_page_residence_identity_for_owner(owner) else { return TargetPreparedOutputs::default(); }; let browser_context_id = owner_page.browser_context_id().to_owned(); - let owner_page_network_sessions = - conn.network_event_session_ids_for_route(session_id, owner_route); + let owner_page_network_sessions = conn.network_event_session_ids_for_owner(owner); dedicated_worker_target_lifecycle_outputs_for_events( conn, browser_context_id, diff --git a/moli-protocol/src/testing.rs b/moli-protocol/src/testing.rs index 9194dfebb2..de9e0fdea6 100644 --- a/moli-protocol/src/testing.rs +++ b/moli-protocol/src/testing.rs @@ -309,7 +309,7 @@ impl TestContext { let owner = crate::conn::CommandOwnerScope::capture(&self.conn, session_id); let (_, target_id) = self .conn - .target_owner_identity_for_route(owner.session_id(), owner.session_owner_route()) + .target_owner_identity_for_owner(&owner) .expect("navigation fixture requires an installed browser context"); let target_id = target_id.expect("navigation fixture requires an exact target"); let navigation_engine = navigation.take_navigation_engine_replacement(); @@ -357,10 +357,8 @@ impl TestContext { .adopt_loaded_navigation_engine_for_owner(&owner, navigation_engine); } assert_eq!( - self.conn.target_root_document_lifecycle_identity_for_route( - owner.session_id(), - owner.session_owner_route(), - ), + self.conn + .target_root_document_lifecycle_identity_for_owner(&owner,), Some(binding.renderer_document_identity()), "navigation fixture must retain its exact renderer Document binding" ); @@ -384,6 +382,16 @@ impl TestContext { .expect("test message must be a valid serialisable CDP command"); let command_id = command.request().id(); let session_id = command.request().session_id().map(str::to_owned); + let command_awaits_promise = match command.request().method() { + "Runtime.awaitPromise" => true, + "Runtime.evaluate" | "Runtime.callFunctionOn" | "Runtime.runScript" => command + .request() + .params() + .and_then(|params| params.get("awaitPromise")) + .and_then(Value::as_bool) + .unwrap_or(false), + _ => false, + }; let response_start = self.sent.len(); Box::pin(self.process_parsed_command_like_scheduler(&command, true)).await; Box::pin(self.route_ready_test_command_response(command_id, response_start)).await; @@ -391,6 +399,10 @@ impl TestContext { .conn .renderer_runtime_command_cause_for_frontend(session_id.as_deref(), command_id) .is_some() + && !(command_awaits_promise + && self + .conn + .has_pending_inspector_awaits_for_session_owner(session_id.as_deref())) && !self .pending_runtime_deferred_replies .iter() diff --git a/moli-renderer-v8/src/lib.rs b/moli-renderer-v8/src/lib.rs index caefe1fc7d..591029f76c 100644 --- a/moli-renderer-v8/src/lib.rs +++ b/moli-renderer-v8/src/lib.rs @@ -217,17 +217,17 @@ pub use runtime::RendererRuntimeInspectorMessageResponseOrder; pub use runtime::{ CompletedWorkerRuntimeInspectorCommandDispatch, DetachedParserScriptFetchContinuation, DevToolsSessionKey, ExternalRawDocumentBodyStream, JsRuntime, JsRuntimeOwner, PageId, - PendingHtmlPage, PreparedRendererDocument, RendererAccessibilityPayloadsForObjectId, - RendererActivityDiagnostics, RendererAgentAttachmentId, RendererAutofillAddressField, - RendererAutofillCreditCard, RendererAutofillTriggerOutcome, RendererAutofillTriggerRequest, - RendererBrowserContextRuntime, RendererBrowserContextRuntimeId, - RendererBrowserContextRuntimeOwner, RendererBrowserContextRuntimeOwnerAccess, - RendererCaptureScreencastFrameReply, RendererCaptureScreencastFrameRequest, - RendererCaptureScreenshotReply, RendererCaptureScreenshotRequest, - RendererCapturedScreencastFrame, RendererCapturedScreenshot, RendererCommandTurnCompletion, - RendererCommandTurnOutput, RendererCountEntry, RendererDedicatedWorkerTargetEvent, - RendererDedicatedWorkerTargetInfo, RendererDevToolsAgentToken, - RendererDevToolsMainCommandEnvelope, RendererDocumentBoxModel, + PendingHtmlPage, PendingWorkerRuntimeInspectorSessionResponse, PreparedRendererDocument, + RendererAccessibilityPayloadsForObjectId, RendererActivityDiagnostics, + RendererAgentAttachmentId, RendererAutofillAddressField, RendererAutofillCreditCard, + RendererAutofillTriggerOutcome, RendererAutofillTriggerRequest, RendererBrowserContextRuntime, + RendererBrowserContextRuntimeId, RendererBrowserContextRuntimeOwner, + RendererBrowserContextRuntimeOwnerAccess, RendererCaptureScreencastFrameReply, + RendererCaptureScreencastFrameRequest, RendererCaptureScreenshotReply, + RendererCaptureScreenshotRequest, RendererCapturedScreencastFrame, RendererCapturedScreenshot, + RendererCommandTurnCompletion, RendererCommandTurnOutput, RendererCountEntry, + RendererDedicatedWorkerTargetEvent, RendererDedicatedWorkerTargetInfo, + RendererDevToolsAgentToken, RendererDevToolsMainCommandEnvelope, RendererDocumentBoxModel, RendererDocumentChildNodeSnapshotEvent, RendererDocumentChildNodeSnapshotEvents, RendererDocumentChildNodeSnapshots, RendererDocumentCommitPermit, RendererDocumentFrontendNodeIdsResolution, RendererDocumentHitTestResult, diff --git a/moli-renderer-v8/src/runtime/browser_context_runtime/dedicated_workers.rs b/moli-renderer-v8/src/runtime/browser_context_runtime/dedicated_workers.rs index 9e1bacd9dd..a23cf73058 100644 --- a/moli-renderer-v8/src/runtime/browser_context_runtime/dedicated_workers.rs +++ b/moli-renderer-v8/src/runtime/browser_context_runtime/dedicated_workers.rs @@ -115,23 +115,31 @@ impl RendererBrowserContextRuntime { }; let response = response .route_to_worker_devtools_session_output(inspector_session_id.clone(), output_journal); + let error_response = response.clone(); let settlement = response .take_session_response_settlement_receiver() .expect("a Worker DevTools response must own one settlement receiver"); let (response_tx, response_rx) = oneshot::channel(); - if !target.handle.dispatch_runtime_protocol_message( + let dispatched = target.handle.dispatch_runtime_protocol_message( Some(inspector_session_id), raw_json, Some(response), response_tx, - ) { - return Err("DedicatedWorkerRuntimeUnavailable".to_owned()); - } - let dispatch = response_rx - .await - .map_err(|_| "DedicatedWorkerRuntimeUnavailable".to_owned())?; - crate::runtime::CompletedWorkerRuntimeInspectorCommandDispatch::finish(dispatch, settlement) - .await + ); + let dispatch = if dispatched { + response_rx + .await + .unwrap_or_else(|_| Err("DedicatedWorkerRuntimeUnavailable".to_owned())) + } else { + Err("DedicatedWorkerRuntimeUnavailable".to_owned()) + }; + Ok( + crate::runtime::CompletedWorkerRuntimeInspectorCommandDispatch::finish( + dispatch, + settlement, + error_response, + ), + ) } async fn dispatch_dedicated_worker_runtime_protocol_message_with_optional_deferred_response( diff --git a/moli-renderer-v8/src/runtime/mod.rs b/moli-renderer-v8/src/runtime/mod.rs index f301b0c93f..5990beaade 100644 --- a/moli-renderer-v8/src/runtime/mod.rs +++ b/moli-renderer-v8/src/runtime/mod.rs @@ -308,9 +308,9 @@ use self::page_surface::RendererPageTable; pub use self::page_surface::RendererRuntimeInspectorMessageResponseOrder; pub use self::page_surface::{ CompletedWorkerRuntimeInspectorCommandDispatch, DevToolsSessionKey, - RendererAccessibilityPayloadsForObjectId, RendererActivityDiagnostics, - RendererAgentAttachmentId, RendererAutofillAddressField, RendererAutofillCreditCard, - RendererAutofillTriggerOutcome, RendererAutofillTriggerRequest, + PendingWorkerRuntimeInspectorSessionResponse, RendererAccessibilityPayloadsForObjectId, + RendererActivityDiagnostics, RendererAgentAttachmentId, RendererAutofillAddressField, + RendererAutofillCreditCard, RendererAutofillTriggerOutcome, RendererAutofillTriggerRequest, RendererCaptureScreencastFrameReply, RendererCaptureScreenshotReply, RendererCapturedScreencastFrame, RendererCapturedScreenshot, RendererCommandTurnCompletion, RendererCommandTurnOutput, RendererCountEntry, RendererDedicatedWorkerTargetEvent, diff --git a/moli-renderer-v8/src/runtime/page_surface.rs b/moli-renderer-v8/src/runtime/page_surface.rs index 11d6e225b4..1778f4608b 100644 --- a/moli-renderer-v8/src/runtime/page_surface.rs +++ b/moli-renderer-v8/src/runtime/page_surface.rs @@ -2749,8 +2749,21 @@ impl RendererRuntimeInspectorSessionResponseSettlement { #[derive(Debug)] pub struct CompletedWorkerRuntimeInspectorCommandDispatch { messages: Vec, - predecessor: RendererOutputFence, - response_succeeded: bool, + pending_session_response: PendingWorkerRuntimeInspectorSessionResponse, +} + +#[derive(Debug)] +pub struct PendingWorkerRuntimeInspectorSessionResponse { + settlement: oneshot::Receiver, +} + +impl PendingWorkerRuntimeInspectorSessionResponse { + pub async fn wait(self) -> Result<(RendererOutputFence, bool), String> { + self.settlement + .await + .map(RendererRuntimeInspectorSessionResponseSettlement::into_parts) + .map_err(|_| "WorkerRuntimeInspectorResponseCanceled".to_owned()) + } } impl CompletedWorkerRuntimeInspectorCommandDispatch { @@ -2758,28 +2771,33 @@ impl CompletedWorkerRuntimeInspectorCommandDispatch { self, ) -> ( Vec, - RendererOutputFence, - bool, + PendingWorkerRuntimeInspectorSessionResponse, ) { - (self.messages, self.predecessor, self.response_succeeded) + (self.messages, self.pending_session_response) } - pub(crate) async fn finish( + pub(crate) fn finish( dispatch: Result, String>, settlement: oneshot::Receiver, - ) -> Result { - match settlement.await { - Ok(settlement) => { - let (predecessor, response_succeeded) = settlement.into_parts(); - Ok(Self { - messages: dispatch.unwrap_or_default(), - predecessor, - response_succeeded, - }) + error_response: RendererRuntimeInspectorResponseSender, + ) -> Self { + let messages = match dispatch { + Ok(messages) => messages, + Err(message) => { + let call_id = error_response.call_id(); + let _ = error_response.send(json!({ + "id": call_id, + "error": { + "code": -32000, + "message": message, + } + })); + Vec::new() } - Err(_) => Err(dispatch - .err() - .unwrap_or_else(|| "WorkerRuntimeInspectorResponseCanceled".to_owned())), + }; + Self { + messages, + pending_session_response: PendingWorkerRuntimeInspectorSessionResponse { settlement }, } } } diff --git a/moli-renderer-v8/src/service_worker_runtime/service/runtime_protocol.rs b/moli-renderer-v8/src/service_worker_runtime/service/runtime_protocol.rs index c18a9dea9e..e11e75ea99 100644 --- a/moli-renderer-v8/src/service_worker_runtime/service/runtime_protocol.rs +++ b/moli-renderer-v8/src/service_worker_runtime/service/runtime_protocol.rs @@ -53,6 +53,7 @@ impl ServiceWorkerRuntimeService { }; let response = response .route_to_worker_devtools_session_output(inspector_session_id.clone(), output_journal); + let error_response = response.clone(); let settlement = response .take_session_response_settlement_receiver() .expect("a Worker DevTools response must own one settlement receiver"); @@ -63,8 +64,13 @@ impl ServiceWorkerRuntimeService { response, ) .await; - crate::runtime::CompletedWorkerRuntimeInspectorCommandDispatch::finish(dispatch, settlement) - .await + Ok( + crate::runtime::CompletedWorkerRuntimeInspectorCommandDispatch::finish( + dispatch, + settlement, + error_response, + ), + ) } pub(crate) fn detach_runtime_inspector_session( diff --git a/moli-renderer-v8/src/shared_worker_runtime/protocol_routing.rs b/moli-renderer-v8/src/shared_worker_runtime/protocol_routing.rs index 92b577da00..2912f13f3e 100644 --- a/moli-renderer-v8/src/shared_worker_runtime/protocol_routing.rs +++ b/moli-renderer-v8/src/shared_worker_runtime/protocol_routing.rs @@ -50,6 +50,7 @@ impl SharedWorkerRuntimeService { inspector_session_id.clone(), host.target_output().clone(), ); + let error_response = response.clone(); let settlement = response .take_session_response_settlement_receiver() .expect("a Worker DevTools response must own one settlement receiver"); @@ -60,8 +61,13 @@ impl SharedWorkerRuntimeService { response, ) .await; - crate::runtime::CompletedWorkerRuntimeInspectorCommandDispatch::finish(dispatch, settlement) - .await + Ok( + crate::runtime::CompletedWorkerRuntimeInspectorCommandDispatch::finish( + dispatch, + settlement, + error_response, + ), + ) } pub(crate) fn detach_runtime_inspector_session(