///|
/// CDP Target Domain
///
/// Manages browser contexts, targets, and sessions.
/// Required for Puppeteer compatibility.
///|
/// Target domain handler
pub struct TargetDomain {
/// All browser contexts
contexts : Map[String, CdpContext]
/// Active browser context ID
mut active_context_id : String?
/// ID generators
mut next_context_id : Int
mut next_target_id : Int
mut next_session_id : Int
/// Auto-attach setting
mut auto_attach : Bool
/// Discover targets setting
mut discover_targets : Bool
}
///|
/// Create new Target domain
pub fn TargetDomain::new() -> TargetDomain {
{
contexts: {},
active_context_id: None,
next_context_id: 1,
next_target_id: 1,
next_session_id: 1,
auto_attach: false,
discover_targets: false,
}
}
///|
/// Target info structure (for CDP responses)
pub struct TargetInfo {
target_id : String
target_type : String // "page", "browser", etc.
title : String
url : String
attached : Bool
browser_context_id : String?
} derive(Debug)
// =============================================================================
// Browser Context Management
// =============================================================================
///|
/// Target.createBrowserContext
pub fn TargetDomain::create_browser_context(
self : TargetDomain,
) -> Result[String, CdpError] {
// Generate context ID
let id = "BID-" + self.next_context_id.to_string()
self.next_context_id += 1
// Create context
let context = CdpContext::new(id)
self.contexts[id] = context
self.active_context_id = Some(id)
Ok(id)
}
///|
/// Target.disposeBrowserContext
pub fn TargetDomain::dispose_browser_context(
self : TargetDomain,
browser_context_id : String,
) -> Result[Unit, CdpError] {
match self.contexts.get(browser_context_id) {
Some(_) => {
self.contexts.remove(browser_context_id)
if self.active_context_id == Some(browser_context_id) {
self.active_context_id = None
}
Ok(())
}
None =>
Err(
CdpError::from_code(
InvalidParams,
"No browser context with the given id found",
),
)
}
}
///|
/// Target.getBrowserContexts
pub fn TargetDomain::get_browser_contexts(self : TargetDomain) -> Array[String] {
let ids : Array[String] = []
for id, _ in self.contexts {
ids.push(id)
}
ids
}
///|
/// Get active browser context
pub fn TargetDomain::get_active_context(self : TargetDomain) -> CdpContext? {
match self.active_context_id {
Some(id) => self.contexts.get(id)
None => None
}
}
///|
/// Get browser context by ID
pub fn TargetDomain::get_context(
self : TargetDomain,
id : String,
) -> CdpContext? {
self.contexts.get(id)
}
// =============================================================================
// Target Management
// =============================================================================
///|
/// Target.createTarget
pub fn TargetDomain::create_target(
self : TargetDomain,
url : String,
browser_context_id : String?,
) -> Result[String, CdpError] {
// Get or create browser context
let context_id : String = match browser_context_id {
Some(id) =>
match self.contexts.get(id) {
Some(_) => id
None =>
return Err(
CdpError::from_code(InvalidParams, "Unknown browser context id"),
)
}
None =>
// Create new context if none specified
match self.active_context_id {
Some(id) => id
None =>
match self.create_browser_context() {
Ok(id) => id
Err(e) => return Err(e)
}
}
}
// Get context
let context = self.contexts.get(context_id).unwrap()
// Check if target already exists
match context.get_target_id() {
Some(_) =>
return Err(CdpError::from_code(InternalError, "Target already exists"))
None => ()
}
// Generate target ID
let target_id = "TID-" + self.next_target_id.to_string()
self.next_target_id += 1
context.set_target_id(target_id)
// Navigate if URL provided
if url != "about:blank" {
let _ = context.navigate(url)
}
// Auto-attach if enabled
if self.auto_attach {
let session_id = "SID-" + self.next_session_id.to_string()
self.next_session_id += 1
context.set_session_id(session_id)
}
Ok(target_id)
}
///|
/// Target.closeTarget
pub fn TargetDomain::close_target(
self : TargetDomain,
target_id : String,
) -> Result[Unit, CdpError] {
// Find context with this target
for _, context in self.contexts {
match context.get_target_id() {
Some(tid) if tid == target_id => {
context.clear_target()
return Ok(())
}
_ => continue
}
}
Err(CdpError::from_code(InvalidParams, "Unknown target id"))
}
///|
/// Target.attachToTarget
pub fn TargetDomain::attach_to_target(
self : TargetDomain,
target_id : String,
) -> Result[String, CdpError] {
// Find context with this target
for _, context in self.contexts {
match context.get_target_id() {
Some(tid) if tid == target_id => {
// Generate session ID if not already attached
let session_id = match context.get_session_id() {
Some(sid) => sid
None => {
let sid = "SID-" + self.next_session_id.to_string()
self.next_session_id += 1
context.set_session_id(sid)
sid
}
}
return Ok(session_id)
}
_ => continue
}
}
Err(CdpError::from_code(InvalidParams, "Unknown target id"))
}
///|
/// Target.detachFromTarget
pub fn TargetDomain::detach_from_target(
self : TargetDomain,
session_id : String?,
target_id : String?,
) -> Result[Unit, CdpError] {
// Find context with this session/target
for _, context in self.contexts {
let matches = match (session_id, target_id) {
(Some(sid), _) => context.get_session_id() == Some(sid)
(_, Some(tid)) => context.get_target_id() == Some(tid)
_ => false
}
if matches {
context.detach()
return Ok(())
}
}
Err(CdpError::from_code(InvalidParams, "Unknown session/target id"))
}
///|
/// Target.getTargets
pub fn TargetDomain::get_targets(self : TargetDomain) -> Array[TargetInfo] {
let targets : Array[TargetInfo] = []
for _, context in self.contexts {
match context.get_target_id() {
Some(target_id) =>
targets.push({
target_id,
target_type: "page",
title: context.get_title(),
url: context.get_url(),
attached: context.is_attached(),
browser_context_id: Some(context.get_id()),
})
None => ()
}
}
targets
}
///|
/// Target.getTargetInfo
pub fn TargetDomain::get_target_info(
self : TargetDomain,
target_id : String?,
) -> Result[TargetInfo, CdpError] {
match target_id {
Some(tid) => {
// Find specific target
for _, context in self.contexts {
match context.get_target_id() {
Some(t) if t == tid =>
return Ok({
target_id: tid,
target_type: "page",
title: context.get_title(),
url: context.get_url(),
attached: context.is_attached(),
browser_context_id: Some(context.get_id()),
})
_ => continue
}
}
Err(CdpError::from_code(InvalidParams, "Unknown target id"))
}
None =>
// Return browser target info
Ok({
target_id: "TID-BROWSER",
target_type: "browser",
title: "about:blank",
url: "about:blank",
attached: true,
browser_context_id: None,
})
}
}
// =============================================================================
// Settings
// =============================================================================
///|
/// Target.setAutoAttach
pub fn TargetDomain::set_auto_attach(
self : TargetDomain,
auto_attach : Bool,
_wait_for_debugger_on_start : Bool,
) -> Unit {
self.auto_attach = auto_attach
}
///|
/// Target.setDiscoverTargets
pub fn TargetDomain::set_discover_targets(
self : TargetDomain,
discover : Bool,
) -> Unit {
self.discover_targets = discover
}
///|
/// Check if auto-attach is enabled
pub fn TargetDomain::is_auto_attach(self : TargetDomain) -> Bool {
self.auto_attach
}