Skip to content
Merged
Show file tree
Hide file tree
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
21 changes: 21 additions & 0 deletions lib/PuppeteerSharp.Tests/CDPSessionTests/CreateCDPSessionTests.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using NUnit.Framework;
using PuppeteerSharp.Cdp;
using PuppeteerSharp.Cdp.Messaging;
using PuppeteerSharp.Helpers;
using PuppeteerSharp.Nunit;

namespace PuppeteerSharp.Tests.CDPSessionTests
Expand Down Expand Up @@ -183,5 +186,23 @@ public async Task ShouldExposeDetachedState()
await client.DetachAsync();
Assert.That(client.Detached, Is.True);
}

[Test, PuppeteerTest("CDPSession.spec", "Target.createCDPSession", "should handle session callbacks when Chrome sends error without sessionId")]
public async Task ShouldHandleSessionCallbacksWhenChromeSendsErrorWithoutSessionId()
{
var client = (CDPSession)await Page.CreateCDPSessionAsync();
var connection = client.Connection;

var fakeSession = new CdpCDPSession(connection, TargetType.Other, "fake-session-id", null);

var sessionsField = typeof(Connection).GetField("_sessions", BindingFlags.Instance | BindingFlags.NonPublic);
var sessions = (AsyncDictionaryHelper<string, CdpCDPSession>)sessionsField!.GetValue(connection);
sessions!.AddItem("fake-session-id", fakeSession);

var exception = Assert.ThrowsAsync<MessageException>(() => fakeSession.SendAsync(
"Runtime.evaluate",
new RuntimeEvaluateRequest { Expression = "1 + 1" }));
Assert.That(exception!.Message, Does.Contain("Session with given id not found"));
}
}
}
2 changes: 2 additions & 0 deletions lib/PuppeteerSharp/Cdp/CdpCDPSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ public override void Close(string closeReason)

internal bool HasPendingCallbacks() => !_callbacks.IsEmpty;

internal bool HasCallback(int id) => _callbacks.ContainsKey(id);

internal List<string> GetPendingProtocolErrors()
{
var result = new List<string>();
Expand Down
14 changes: 14 additions & 0 deletions lib/PuppeteerSharp/Cdp/Connection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,20 @@ private void ProcessIncomingMessage(ConnectionResponse obj)
{
MessageQueue.Enqueue(callback, obj);
}
else
{
// Chrome can occasionally omit the sessionId on responses. Fall back
// to a per-session callback lookup so the response is routed to the
// session that originally issued the command (upstream #14975).
foreach (var session in _sessions.Values)
{
if (session.HasCallback(obj.Id.Value))
{
session.OnMessage(obj);
break;
}
}
}
}
else
{
Expand Down
Loading