refactor(cdp): remove ambiguous owner routing adapters

This commit is contained in:
ldm0
2026-09-04 04:39:43 +08:00
committed by Donough Liu
parent 963de5c520
commit baeab149b9
100 changed files with 3410 additions and 5062 deletions
+3 -2
View File
@@ -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,
+154 -218
View File
@@ -816,8 +816,7 @@ impl DeferredMainDocumentLoadPredecessorCandidate {
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct RuntimeAwaitJob {
command_id: u64,
session_id: Option<String>,
owner_route: Option<CdpSessionRoute>,
owner: CommandOwnerScope,
object_group: Option<String>,
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<CdpSessionRoute>,
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<String> {
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<String> {
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<String> {
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<String> {
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<String> {
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<crate::domains::network::TargetNetworkBacklogPreparedDelivery> {
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<RendererPageResidenceIdentity>,
source_document: moli_core::RendererDocumentLifecycleIdentity,
item: &moli_core::page::ScriptNetworkOutputItem,
) -> Option<crate::domains::network::TargetNetworkBacklogPreparedDelivery> {
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<DocumentNavigationToken> {
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<moli_core::page::RendererDocumentLifecycleEvent>,
) {
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<moli_core::page::RendererDocumentLifecycleEvent>,
) {
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<Vec<moli_core::page::RendererDocumentLifecycleEvent>> {
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<BackgroundProtocolEvent>,
) -> 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<DevToolsPageResidenceIdentity> {
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<DevToolsDocumentLifecycleWaitKey> {
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<crate::domains::page::BackgroundNavigationCompletion>,
> {
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();
};
+6 -19
View File
@@ -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<PendingChildFrameLifecycleWork, String> {
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)
+2 -5
View File
@@ -23,10 +23,7 @@ impl BidiChannelPageOwner {
owner_scope: CommandOwnerScope,
) -> Option<Self> {
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"
);
@@ -94,16 +94,16 @@ impl CdpConnection {
session_id: Option<&str>,
f: impl FnOnce(Option<TargetEmulationSessionStateMut<'_>>),
) -> 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<TargetEmulationSessionStateMut<'_>>),
) -> 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<String>,
) -> 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<String>,
) -> 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))
}
@@ -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<TargetFetchSubresourceInterceptionSnapshot> {
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<String> {
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<DevToolsNetworkInterceptId> {
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<String, String> {
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<String, String> {
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<String, 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(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<u64> {
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<u64> {
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<crate::conn::ClaimedSubresourceContinueRequest> {
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<Result<(), &'static str>> {
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<PendingFetchNavigation> {
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<PendingFetchAuthNavigation> {
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<crate::conn::DocumentNavigationToken>,
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<PausedDocumentTransfer> {
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<PausedDocumentTransfer> {
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<PendingSubresourceFetchResponseRequest> {
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<PendingSubresourceFetchRequest> {
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<PendingSubresourceFetchAuthRequest> {
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<PendingSubresourceFetchResponseRequest> {
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<InFlightSubresourceFetchRequest> {
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<String> {
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<String>,
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<String>,
pending: PendingSubresourceFetchRequest,
response_stage_blocked_intercepts: Vec<DevToolsNetworkInterceptId>,
) -> 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<String>,
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<FetchInterceptionPattern>,
) -> Result<Option<moli_core::page::PendingPageCommand>, 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<FetchInterceptionPattern>,
) -> Result<Option<moli_core::page::PendingPageCommand>, 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<String>,
intercept_id: String,
handle_auth_requests: bool,
auth_url_patterns: Vec<String>,
patterns: Vec<FetchInterceptionPattern>,
) -> Result<Option<moli_core::page::PendingPageCommand>, 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<Option<moli_core::page::PendingPageCommand>, 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<SessionOwnerPendingFetchState> {
Some(
self.target_session_owner_mut_for_route(session_id, owner_route)?
self.target_session_owner_mut_for_owner(owner)?
.drain_fetch_pending_state(),
)
}
@@ -356,23 +356,17 @@ impl CdpConnection {
data_type: DevToolsNetworkDataType,
encoded_data_size: usize,
) -> Vec<String> {
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<String> {
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<NetworkBacklogPreferredRequestId<'_>>,
@@ -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<NetworkBacklogPreferredRequestId<'_>>,
@@ -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<Option<String>> {
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<Option<String>> {
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<Option<PendingPageCommand>, 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<String>,
) -> Result<Option<PendingPageCommand>, 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<String>,
) -> Result<Option<PendingPageCommand>, 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<String>,
) -> Result<Option<PendingPageCommand>, 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");
@@ -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<bool> {
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<bool> {
self.target_session_owner_ref_for_route(session_id, owner_route)
pub(crate) fn page_domain_enabled_for_owner(&self, owner: &CommandOwnerScope) -> Option<bool> {
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<crate::conn::CapturedBody>,
) -> 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<String, Value>,
) -> 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<bool> {
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<bool> {
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<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.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<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_performance_time_domain(time_domain)
})
@@ -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()
@@ -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<R>(
&mut self,
pub(super) fn accepts_unmaterialized_page_command_for_session(
&self,
session_id: Option<&str>,
f: impl FnOnce(&mut BrowserContext, &str) -> R,
) -> Option<R> {
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<TargetSessionOwner> {
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<TargetSessionOwner> {
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));
}
}
File diff suppressed because it is too large Load Diff
+90 -24
View File
@@ -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<CdpSessionRoute> {
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",
);
}
}
+1 -4
View File
@@ -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;
+53 -42
View File
@@ -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!(
+37 -41
View File
@@ -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<BackgroundProtocolEvent>,
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<BackgroundProtocolEvent>,
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<BackgroundProtocolEvent>,
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<Option<PreparedDownloadActivation>, 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<Option<Vec<BackgroundProtocolEvent>>, 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<Option<PreparedNavigationDownload>, 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<Option<PreparedNavigationDownload>, 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<PendingDownloadOwnerContext> {
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!(
+36 -53
View File
@@ -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<PendingSubresourceContinueOutcome, String> {
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<Url>,
method: Option<String>,
@@ -2083,7 +2082,7 @@ impl CdpConnection {
handle_auth_requests: bool,
) -> Result<PendingSubresourceContinueOutcome, 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_fetch_async(
@@ -2114,19 +2113,19 @@ impl CdpConnection {
internal_id: u64,
auth: SubresourceAuthCredentials,
) -> Result<PendingSubresourceContinueOutcome, String> {
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<PendingSubresourceContinueOutcome, 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_auth_async(internal_id, auth)
@@ -2149,24 +2148,19 @@ impl CdpConnection {
internal_id: u64,
error_text: String,
) -> Result<Option<moli_core::RendererOutputFence>, 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<Option<moli_core::RendererOutputFence>, 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<Option<moli_core::RendererOutputFence>, 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<Option<moli_core::RendererOutputFence>, 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<u16>,
response_headers: Option<Vec<(String, String)>>,
) -> 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<u16>,
response_headers: Option<Vec<(String, 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.continue_pending_subresource_response_async(
@@ -2325,24 +2313,19 @@ impl CdpConnection {
internal_id: u64,
error_text: String,
) -> Result<Option<moli_core::RendererOutputFence>, 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<Option<moli_core::RendererOutputFence>, 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)
+20 -40
View File
@@ -25,7 +25,7 @@ impl CdpConnection {
&self,
owner: &CommandOwnerScope,
) -> Option<RendererAgentAttachmentId> {
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<PreparedRendererAgentAttachment, String> {
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<RendererRuntimeInspectorMessageBatch>,
) -> Vec<RendererRuntimeInspectorMessageBatch> {
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::<Vec<_>>();
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<CommittedRendererAgentAttachment, String> {
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<RendererRuntimeInspectorMessageBatch>,
) -> Vec<RendererRuntimeInspectorMessageBatch> {
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());
@@ -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<PendingFetchNavigation>,
Vec<PendingFetchAuthNavigation>,
Vec<PausedDocumentTransfer>,
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
@@ -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();
}
@@ -227,15 +227,15 @@ impl CdpConnection {
&mut self,
session_id: Option<&str>,
) -> Result<Option<PendingPageCommand>, 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<Option<PendingPageCommand>, 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()
}
}
File diff suppressed because it is too large Load Diff
+77 -145
View File
@@ -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<PreparedDocumentPageCommitConfiguration, String> {
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<Option<PendingInitialDocumentPageBuild>, 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<Option<PendingInitialDocumentPageBuild>, 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<Url> {
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<LoadedNavigation, String> {
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<NavigationLoadOutcome, String> {
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<NetworkFetchResult<RawResponse>, 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<SubresourceAuthCredentials>,
) -> Result<NetworkFetchResult<StreamingRawResponse>, 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<RawResponse>,
) -> Result<NavigationLoadOutcome, String> {
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<NavigationLoadOutcome, String> {
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,
+8 -3
View File
@@ -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()
+23 -39
View File
@@ -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<String> {
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")
);
}
+8 -4
View File
@@ -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"
);
}
@@ -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,
}
+2 -5
View File
@@ -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(
@@ -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(),
@@ -47,11 +47,9 @@ impl PreparedProtocolOutputs {
source_document: moli_core::RendererDocumentLifecycleIdentity,
item: &moli_core::page::ScriptNetworkOutputItem,
) -> Option<Self> {
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,
@@ -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<moli_core::RendererOutputRecord>,
@@ -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()),
@@ -157,14 +157,10 @@ impl RuntimeCommandCausalOwner {
}
fn capture_for_scope(conn: &CdpConnection, scope: &CommandOwnerScope) -> Option<Self> {
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,
@@ -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<Self> {
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<PreparedSubresourceContinueAction> {
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<PreparedSubresourceContinueAction>,
) {
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(),
+1 -3
View File
@@ -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())
+1 -4
View File
@@ -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(
+5 -2
View File
@@ -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)
+14 -27
View File
@@ -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<String> {
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<Value> {
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) {
+1 -4
View File
@@ -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 {
+81 -189
View File
@@ -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<String> {
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<DevToolsCommandResult, PendingDomCommandStartError> {
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<DevToolsDomNodeReference>,
selector: &str,
multiple: bool,
) -> Result<DevToolsQuerySelectorResult, PendingDomCommandStartError> {
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<DevToolsDomNodeReference>,
selector: &str,
multiple: bool,
) -> Result<DevToolsQuerySelectorResult, PendingDomCommandStartError> {
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<DevToolsDomNodeReference, PendingDomCommandStartError> {
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<RendererDocumentNodeReference, PendingDomCommandStartError> {
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<DevToolsGetAttributesResult, PendingDomCommandStartError> {
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<DevToolsGetTextResult, PendingDomCommandStartError> {
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<DevToolsGetPropertyResult, PendingDomCommandStartError> {
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<DevToolsDomNodeReference>,
include_shadow_dom: bool,
) -> Result<String, PendingDomCommandStartError> {
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<DevToolsDomNodeReference>,
include_shadow_dom: bool,
) -> Result<String, PendingDomCommandStartError> {
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<DevToolsResolveNodeResult, PendingDomCommandStartError> {
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<DevToolsResolveNodeResult, PendingDomCommandStartError> {
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<DevToolsDescribeNodeResult, PendingDomCommandStartError> {
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<moli_core::page::DocumentNodeSnapshot, PendingDomCommandStartError> {
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<moli_core::page::DocumentNodeSnapshot, PendingDomCommandStartError> {
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<moli_core::page::DocumentNodeSnapshot, PendingDomCommandStartError> {
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<DevToolsDomGeometryResult, PendingDomCommandStartError> {
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<RendererDocumentNodeGeometry, PendingDomCommandStartError> {
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<RendererDocumentNodeGeometry, PendingDomCommandStartError> {
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
+76 -206
View File
@@ -318,11 +318,8 @@ pub(super) fn start_disable_dom_agent_command(
cmd: &Cmd<'_>,
) -> Result<Option<PendingDomCommandDispatch>, 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<PendingDomCommandDispatch, PendingDomCommandStartError> {
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<Option<PendingDomCommandDispatch>, 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<Option<PendingDomCommandDispatch>, 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<Option<PendingDomCommandDispatch>, 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<Option<PendingDomCommandDispatch>, 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<Option<PendingDomCommandDispatch>, 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<Option<PendingDomCommandDispatch>, 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<Option<PendingDomCommandDispatch>, 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::<Vec<_>>();
@@ -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<String>,
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<String>,
) -> 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<String>,
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<String>,
) -> 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<String>,
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<String>,
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<String>,
top_frame_id: Option<String>,
) -> 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<Option<PendingDomCommandDispatch>, 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<DevToolsCommandResult, DevToolsError> {
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<String>, Option<String>), 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(
+7 -20
View File
@@ -83,16 +83,9 @@ pub(super) fn start_devtools_perform_search_command(
owner: &CommandOwnerScope,
command: DevToolsPerformSearchCommand,
) -> Result<Option<PendingDomCommandDispatch>, 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<Option<PendingDomCommandDispatch>, 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<Option<PendingDomCommandDispatch>, 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);
};
@@ -101,11 +101,8 @@ pub(super) fn start_devtools_set_file_input_files_command(
) -> Result<Option<PendingDomCommandDispatch>, 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<String>,
append: bool,
) -> Result<Option<PendingDomCommandDispatch>, 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<PendingDomCommandDispatch, 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 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;
+4 -10
View File
@@ -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
+25 -35
View File
@@ -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) => {
+1 -3
View File
@@ -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(
@@ -77,9 +77,7 @@ fn dom_storage_subscriptions_for_browser_context_owner(
conn: &CdpConnection,
owner: &CommandOwnerScope,
) -> Vec<(Option<String>, 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<String>, 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
@@ -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<BrowserContextPageStorageHandles, CommandOutputPlan> {
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<BrowserContextPageStorageHandles, CommandOutputPlan> {
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,
+89 -90
View File
@@ -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<u64>,
command: DevToolsSetViewportCommand,
owner_route: Option<&CdpSessionRoute>,
owner_scope: CommandOwnerScope,
) -> Result<Option<PendingEmulationCommandDispatch>, 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<EmulatedDeviceMetrics, DevToolsError> {
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<EmulatedGeolocationOverrideState>,
) -> Result<Vec<PendingEmulationPageCommand>, 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<DevToolsNetworkConditions>,
) -> Result<Vec<PendingEmulationPageCommand>, 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<Vec<PendingEmulationPageCommand>, 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<String>,
) -> Result<Option<PendingEmulationPageCommand>, 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<Option<PendingEmulationPageCommand>, 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<String>,
) -> Result<Vec<PendingEmulationPageCommand>, 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<String>,
) -> Result<Option<PendingEmulationPageCommand>, 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<Option<PendingEmulationPageCommand>, 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<DevToolsCommandResult, DevToolsError> {
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<Vec<PendingEmulationPageCommand>, 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<Vec<PendingEmulationPageCommand>, 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<Option<String>> {
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<Option<String>> {
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)
}
+2 -3
View File
@@ -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");
+47 -70
View File
@@ -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<String>, Option<CdpSessionRoute>), DevToolsError> {
) -> Result<CommandOwnerScope, DevToolsError> {
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<String>, Option<CdpSessionRoute>), DevToolsError> {
let response_session_id = context
.session_id
.as_ref()
.map(|session| session.as_str().to_owned());
context: &crate::devtools_runtime::DevToolsCommandContext,
) -> Result<CommandOwnerScope, DevToolsError> {
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(),
)
+19 -45
View File
@@ -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<CompletedPageCommand, String>>,
) -> 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}"))
+7 -20
View File
@@ -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(),
&params.request_id,
) {
if let Some(transfer) = conn
.take_pending_fetch_response_transfer_for_body_read_for_owner(&owner, &params.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)
}
};
+43 -121
View File
@@ -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<CompletedPageCommand, String>>,
) -> 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",
)
+43 -72
View File
@@ -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<NetworkObservationJournal>,
) {
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<DevToolsNetworkInterceptId>,
) {
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,
);
+16 -50
View File
@@ -27,9 +27,8 @@ impl PreparedSubresourceCorrelation {
should_register: bool,
) -> Option<Self> {
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<Self> {
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<PendingFetchNavigation> {
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<PendingFetchAuthNavigation> {
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<PendingSubresourceFetchRequest> {
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<PendingSubresourceFetchAuthRequest> {
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<PendingSubresourceFetchResponseRequest> {
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<PendingSubresourceFetchResponseRequest> {
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,
)
+15 -28
View File
@@ -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<network::TargetSubresourceFetchPauseOutput> {
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.
@@ -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",
)
@@ -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!(
@@ -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!(
@@ -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"),
+21 -34
View File
@@ -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<Option<PendingInputCommandDispatch>, 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<PendingPageCommand>,
) -> Result<Option<PendingInputCommandDispatch>, 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<BackgroundProtocolEvent>,
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<BackgroundProtocolEvent>,
session_id: Option<&str>,
owner: &CommandOwnerScope,
activations: Vec<RendererPendingDownloadActivation>,
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<BackgroundProtocolEvent>,
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;
+17 -29
View File
@@ -35,9 +35,7 @@ impl PreparedFileChooserActivation {
page_owner: TargetPageResidenceIdentity,
activation: RendererPendingFileChooserActivation,
) -> Option<Self> {
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<BackgroundProtocolEvent>,
session_id: Option<&str>,
owner: &CommandOwnerScope,
activations: Vec<PreparedFileChooserActivation>,
) {
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<BackgroundProtocolEvent>,
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,
)
+4 -2
View File
@@ -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,<body>replacement-before-completion</body>";
@@ -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, "<body>origin</body>").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,<body>replacement-after-ack</body>",
+7 -25
View File
@@ -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)
+15 -22
View File
@@ -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"
);
+28 -70
View File
@@ -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<DevToolsNetworkInterceptId> {
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<PendingNetworkBacklogDeliverySnapshot> {
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<String>],
) {
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<String>],
) {
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(
@@ -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,
@@ -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!({
@@ -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<super::TargetRuntimeObservableSourceOutput> {
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<i64>,
owner: &CommandOwnerScope,
) -> Option<super::TargetRuntimeObservableSourceOutput> {
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;
};
@@ -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<i64, usize>, 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()
}
File diff suppressed because it is too large Load Diff
+11 -14
View File
@@ -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,
+24 -42
View File
@@ -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)
}
@@ -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(),
+85 -176
View File
@@ -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(&current), 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<u64>,
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<ResolvedDevToolsHistoryTraversal, DevToolsError> {
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<u64>,
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<Option<String>> {
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<String>],
) {
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<String>],
) {
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<NavigateCommandStart, CommandOutputPlan> {
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<BackgroundProtocolEvent>,
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<BackgroundProtocolEvent>,
session_id: Option<&str>,
owner: &CommandOwnerScope,
navigations: Vec<super::PagePreparedSameDocumentNavigation>,
) {
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,
@@ -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(
+41 -70
View File
@@ -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<String, DevToolsError> {
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<String, DevToolsError> {
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<String, DevToolsError> {
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())
@@ -299,7 +299,7 @@ fn complete_error(message: impl Into<String>) -> 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()
}
+25 -54
View File
@@ -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<RendererOutputFence> {
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<BackgroundProtocolEvent> {
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(
@@ -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,
),
+49 -82
View File
@@ -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()
+228 -245
View File
@@ -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<String>,
session_id: Option<String>,
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(&current_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<crate::conn::CommandOwnerScope> {
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<RendererRuntimeInspectorMessageBatch>,
) -> 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::<Vec<_>>();
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::<Vec<_>>();
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, "<!doctype html><main>batch order</main>").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, "<!doctype html><main>capture</main>").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, "<!doctype html><main>old</main>").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, "<!doctype html><main>detach</main>").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, "<!doctype html><main>attached</main>").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::<Vec<_>>();
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, "<!doctype html><main>first</main>").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::<Vec<_>>();
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"
);
+9 -15
View File
@@ -18,11 +18,9 @@ pub(super) fn persist_runtime_binding_definition_for_owner(
name: String,
execution_context_name: Option<String>,
) -> 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())
}
+142 -104
View File
@@ -480,6 +480,9 @@ struct RuntimeBindingCommandTask {
execution_context_id: Option<i64>,
inspector_json: Option<String>,
command_response: Option<RuntimeBindingCommandResponse>,
response_delivery: RendererInspectorResponseDelivery,
session_response_predecessor: Option<moli_core::RendererOutputFence>,
session_response_succeeded: Option<bool>,
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<u64>,
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<PendingRuntimeProtocolMessageDispatch, String> {
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<BackgroundProtocolEvent>,
) {
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<CompletedRuntimeProtocolMessageDispatch, String>,
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 => {
@@ -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, "<html><title>ok</title><body></body></html>").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]
@@ -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, "<!doctype html><body></body>").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")]
@@ -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(
+1 -5
View File
@@ -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),
}
+11 -35
View File
@@ -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()
}
+6 -8
View File
@@ -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| {
+8 -13
View File
@@ -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<BackgroundProtocolEvent>,
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(
@@ -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),
@@ -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!(
@@ -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,
+17 -5
View File
@@ -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()
+11 -11
View File
@@ -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,
@@ -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(
+3 -3
View File
@@ -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,
+36 -18
View File
@@ -2749,8 +2749,21 @@ impl RendererRuntimeInspectorSessionResponseSettlement {
#[derive(Debug)]
pub struct CompletedWorkerRuntimeInspectorCommandDispatch {
messages: Vec<RendererRuntimeInspectorMessage>,
predecessor: RendererOutputFence,
response_succeeded: bool,
pending_session_response: PendingWorkerRuntimeInspectorSessionResponse,
}
#[derive(Debug)]
pub struct PendingWorkerRuntimeInspectorSessionResponse {
settlement: oneshot::Receiver<RendererRuntimeInspectorSessionResponseSettlement>,
}
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<RendererRuntimeInspectorMessage>,
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<Vec<RendererRuntimeInspectorMessage>, String>,
settlement: oneshot::Receiver<RendererRuntimeInspectorSessionResponseSettlement>,
) -> Result<Self, String> {
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 },
}
}
}
@@ -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(
@@ -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(