Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 45 additions & 27 deletions lib/PuppeteerSharp/Cdp/ChromeTargetManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,14 @@ private async Task OnTargetDestroyedAsync(string messageId, TargetDestroyedRespo
await EnsureTargetsIdsForInitAsync().ConfigureAwait(false);
FinishInitializationIfReady(e.TargetId);

if (targetInfo?.Type == TargetType.ServiceWorker && _attachedTargetsByTargetId.TryRemove(e.TargetId, out var target))
if (targetInfo?.Type == TargetType.ServiceWorker)
{
TargetGone?.Invoke(this, new TargetChangedArgs { Target = target, TargetInfo = targetInfo });
// Special case for service workers: report TargetGone event when
// the worker is destroyed.
if (_attachedTargetsByTargetId.TryRemove(e.TargetId, out var target))
{
TargetGone?.Invoke(this, new TargetChangedArgs { Target = target, TargetInfo = targetInfo });
}
}
Comment on lines +195 to 203
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 'if' statements can be combined.

Copilot uses AI. Check for mistakes.
}
catch (Exception ex)
Expand Down Expand Up @@ -238,6 +243,30 @@ private void OnTargetInfoChanged(TargetCreatedResponse e)
private bool IsPageTargetBecomingPrimary(Target target, TargetInfo newTargetInfo)
=> !string.IsNullOrEmpty(target.TargetInfo.Subtype) && string.IsNullOrEmpty(newTargetInfo.Subtype);

private async Task SilentDetachAsync(CDPSession session, ICDPConnection parentConnection)
{
try
{
await session.SendAsync("Runtime.runIfWaitingForDebugger").ConfigureAwait(false);

// We don't use session.Detach() because that dispatches all commands on
// the connection instead of the parent session.
await parentConnection.SendAsync(
"Target.detachFromTarget",
new TargetDetachFromTargetRequest
{
SessionId = session.Id,
}).ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.LogError(ex, "silentDetach failed.");
}
}

private CdpTarget GetParentTarget(ICDPConnection parentConnection)
=> parentConnection is CdpCDPSession parentSession ? parentSession.Target as CdpTarget : null;

private async Task OnAttachedToTargetAsync(object sender, TargetAttachedToTargetResponse e)
{
var parentConnection = sender as ICDPConnection;
Expand All @@ -255,7 +284,7 @@ private async Task OnAttachedToTargetAsync(object sender, TargetAttachedToTarget
{
await EnsureTargetsIdsForInitAsync().ConfigureAwait(false);
FinishInitializationIfReady(targetInfo.TargetId);
await SilentDetach().ConfigureAwait(false);
await SilentDetachAsync(session, parentConnection).ConfigureAwait(false);
if (_attachedTargetsByTargetId.ContainsKey(targetInfo.TargetId))
{
return;
Expand All @@ -274,12 +303,18 @@ private async Task OnAttachedToTargetAsync(object sender, TargetAttachedToTarget
target = _targetFactoryFunc(targetInfo, session, parentSession);
}

var parentTarget = GetParentTarget(parentConnection);

if (_targetFilterFunc?.Invoke(target) == false)
{
_ignoredTargets.Add(targetInfo.TargetId);
await EnsureTargetsIdsForInitAsync().ConfigureAwait(false);
FinishInitializationIfReady(targetInfo.TargetId);
await SilentDetach().ConfigureAwait(false);
if (parentTarget?.TargetInfo.Type == TargetType.Tab)
{
FinishInitializationIfReady(parentTarget.TargetId);
}

await SilentDetachAsync(session, parentConnection).ConfigureAwait(false);
return;
}

Expand All @@ -298,7 +333,6 @@ private async Task OnAttachedToTargetAsync(object sender, TargetAttachedToTarget
_attachedTargetsBySessionId.TryAdd(session.Id, target);
}

var parentTarget = parentSession?.Target;
parentTarget?.AddChildTarget(target);
(parentSession ?? parentConnection as CDPSession)?.OnSessionReady(session);

Expand Down Expand Up @@ -327,26 +361,6 @@ await Task.WhenAll(
{
_logger.LogError(ex, "Failed to call setAutoAttach and runIfWaitingForDebugger");
}

return;

async Task SilentDetach()
{
try
{
await session.SendAsync("Runtime.runIfWaitingForDebugger").ConfigureAwait(false);
await parentConnection!.SendAsync(
"Target.detachFromTarget",
new TargetDetachFromTargetRequest
{
SessionId = session.Id,
}).ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.LogError(ex, "silentDetach failed.");
}
}
}

private async Task OnAttachedToTargetHandlingExceptionsAsync(object sender, string messageId, TargetAttachedToTargetResponse e)
Expand Down Expand Up @@ -388,7 +402,11 @@ private void OnDetachedFromTarget(object sender, TargetDetachedFromTargetRespons
return;
}

(sender as CdpCDPSession)?.Target.RemoveChildTarget(target);
if (sender is CdpCDPSession parentSession)
{
parentSession.Target.RemoveChildTarget(target);
}

_attachedTargetsByTargetId.TryRemove(target.TargetId, out _);
TargetGone?.Invoke(this, new TargetChangedArgs { Target = target });
}
Expand Down
Loading