From fc77be3b5db050aeca3d70a645eb1f21cd6a60d1 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Fri, 8 Dec 2023 15:29:00 -0800 Subject: [PATCH 1/4] chore: move channel events into impl classes --- src/Playwright/Core/Browser.cs | 12 +- src/Playwright/Core/BrowserContext.cs | 190 +++++++++++------- src/Playwright/Core/CDPSession.cs | 13 +- src/Playwright/Core/ElementHandle.cs | 11 +- src/Playwright/Core/Frame.cs | 98 +++++---- src/Playwright/Core/JsonPipe.cs | 24 ++- src/Playwright/Core/Page.cs | 69 +++++-- src/Playwright/Core/WebSocket.cs | 56 +++++- src/Playwright/Core/Worker.cs | 43 ++-- src/Playwright/Transport/ChannelOwnerBase.cs | 5 + .../Transport/Channels/BrowserChannel.cs | 13 -- .../Channels/BrowserContextChannel.cs | 82 -------- .../Transport/Channels/CDPChannel.cs | 8 - .../Transport/Channels/ChannelBase.cs | 6 - .../Channels/ElementHandleChannel.cs | 13 -- .../Transport/Channels/FrameChannel.cs | 34 ---- .../Transport/Channels/JsonPipeChannel.cs | 28 --- .../Transport/Channels/PageChannel.cs | 74 ------- .../Transport/Channels/WebSocketChannel.cs | 57 ------ .../Transport/Channels/WorkerChannel.cs | 13 -- src/Playwright/Transport/Connection.cs | 3 +- 21 files changed, 357 insertions(+), 495 deletions(-) diff --git a/src/Playwright/Core/Browser.cs b/src/Playwright/Core/Browser.cs index b544c63066..63fba13eb6 100644 --- a/src/Playwright/Core/Browser.cs +++ b/src/Playwright/Core/Browser.cs @@ -25,6 +25,7 @@ using System; using System.Collections.Generic; using System.Runtime.CompilerServices; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.Playwright.Transport; using Microsoft.Playwright.Transport.Channels; @@ -44,7 +45,6 @@ internal Browser(IChannelOwner parent, string guid, BrowserInitializer initializ { Channel = new(guid, parent.Connection, this); IsConnected = true; - Channel.Closed += (_, _) => DidClose(); _initializer = initializer; } @@ -66,6 +66,16 @@ internal Browser(IChannelOwner parent, string guid, BrowserInitializer initializ public IBrowserType BrowserType => _browserType; + internal override void OnMessage(string method, JsonElement? serverParams) + { + switch (method) + { + case "close": + DidClose(); + break; + } + } + [MethodImpl(MethodImplOptions.NoInlining)] public async Task CloseAsync(BrowserCloseOptions options = default) { diff --git a/src/Playwright/Core/BrowserContext.cs b/src/Playwright/Core/BrowserContext.cs index ee0c4ab9a4..859ebb67a3 100644 --- a/src/Playwright/Core/BrowserContext.cs +++ b/src/Playwright/Core/BrowserContext.cs @@ -60,83 +60,6 @@ internal BrowserContext(IChannelOwner parent, string guid, BrowserContextInitial _browser = parent as Browser; _browser?._contexts.Add(this); Channel = new(guid, parent.Connection, this); - Channel.Close += (_, _) => OnClose(); - Channel.Console += (_, consoleMessageEvent) => - { - var consoleMessage = new ConsoleMessage(consoleMessageEvent); - _consoleImpl?.Invoke(this, consoleMessage); - if (consoleMessage.Page != null) - { - (consoleMessage.Page as Page).FireConsole(consoleMessage); - } - }; - Channel.Dialog += (_, dialog) => - { - bool hasListeners = _dialogImpl?.GetInvocationList().Length > 0 || ((dialog?.Page as Page)?.HasDialogListenersAttached() ?? false); - if (!hasListeners) - { - // Although we do similar handling on the server side, we still need this logic - // on the client side due to a possible race condition between two async calls: - // a) removing "dialog" listener subscription (client->server) - // b) actual "dialog" event (server->client) - if ("beforeunload".Equals(dialog.Type, StringComparison.Ordinal)) - { - dialog.AcceptAsync().IgnoreException(); - } - else - { - dialog.DismissAsync().IgnoreException(); - } - } - else - { - _dialogImpl?.Invoke(this, dialog); - (dialog.Page as Page)?.FireDialog(dialog); - } - }; - Channel.Page += Channel_OnPage; - Channel.PageError += (_, e) => - { - var pageObject = e.Page?.Object; - var parsedError = string.IsNullOrEmpty(e.Error.Error.Stack) ? $"{e.Error.Error.Name}: {e.Error.Error.Message}" : e.Error.Error.Stack; - WebError?.Invoke(this, new WebError(pageObject, parsedError)); - pageObject?.FirePageError(parsedError); - }; - Channel.BindingCall += Channel_BindingCall; - Channel.Route += Channel_Route; - Channel.RequestFailed += (_, e) => - { - e.Request.Failure = e.FailureText; - e.Request.SetResponseEndTiming(e.ResponseEndTiming); - _requestFailedImpl?.Invoke(this, e.Request); - e.Page?.FireRequestFailed(e.Request); - e.Response?.ReportFinished(e.FailureText); - }; - Channel.Request += (_, e) => - { - _requestImpl?.Invoke(this, e.Request); - e.Page?.FireRequest(e.Request); - }; - Channel.RequestFinished += (_, e) => - { - e.Request.SetResponseEndTiming(e.ResponseEndTiming); - e.Request.Sizes = e.RequestSizes; - _requestFinishedImpl?.Invoke(this, e.Request); - e.Page?.FireRequestFinished(e.Request); - e.Response?.ReportFinished(); - }; - Channel.Response += (_, e) => - { - _responseImpl?.Invoke(this, e.Response); - e.Page?.FireResponse(e.Response); - }; - - Channel.ServiceWorker += (_, serviceWorker) => - { - ((Worker)serviceWorker).Context = this; - _serviceWorkers.Add(serviceWorker); - ServiceWorker?.Invoke(this, serviceWorker); - }; _tracing = initializer.Tracing; _request = initializer.RequestContext; @@ -225,6 +148,117 @@ public ITracing Tracing public IReadOnlyList ServiceWorkers => _serviceWorkers; + internal override void OnMessage(string method, JsonElement? serverParams) + { + switch (method) + { + case "close": + OnClose(); + break; + case "bindingCall": + Channel_BindingCall( + serverParams?.GetProperty("binding").ToObject(_connection.DefaultJsonSerializerOptions).Object); + break; + case "dialog": + OnDialog(serverParams?.GetProperty("dialog").ToObject(_connection.DefaultJsonSerializerOptions).Object); + break; + case "console": + var consoleMessage = new ConsoleMessage(serverParams?.ToObject(_connection.DefaultJsonSerializerOptions)); + _consoleImpl?.Invoke(this, consoleMessage); + if (consoleMessage.Page != null) + { + (consoleMessage.Page as Page).FireConsole(consoleMessage); + } + break; + case "route": + var route = serverParams?.GetProperty("route").ToObject(_connection.DefaultJsonSerializerOptions).Object; + Channel_Route(this, route); + break; + case "page": + Channel_OnPage( + this, + serverParams?.GetProperty("page").ToObject(_connection.DefaultJsonSerializerOptions)); + break; + case "pageError": + { + var error = serverParams?.GetProperty("error").ToObject(_connection.DefaultJsonSerializerOptions); + var pageChannel = serverParams?.GetProperty("page").ToObject(_connection.DefaultJsonSerializerOptions); + var pageObject = pageChannel?.Object; + var parsedError = string.IsNullOrEmpty(error.Error.Stack) ? $"{error.Error.Name}: {error.Error.Message}" : error.Error.Stack; + WebError?.Invoke(this, new WebError(pageObject, parsedError)); + pageObject?.FirePageError(parsedError); + break; + } + case "serviceWorker": + { + var serviceWorker = serverParams?.GetProperty("worker").ToObject(_connection.DefaultJsonSerializerOptions).Object; + ((Worker)serviceWorker).Context = this; + _serviceWorkers.Add(serviceWorker); + ServiceWorker?.Invoke(this, serviceWorker); + break; + } + case "request": + { + var e = serverParams?.ToObject(_connection.DefaultJsonSerializerOptions); + _requestImpl?.Invoke(this, e.Request); + e.Page?.FireRequest(e.Request); + break; + } + case "requestFinished": + { + var e = serverParams?.ToObject(_connection.DefaultJsonSerializerOptions); + e.Request.SetResponseEndTiming(e.ResponseEndTiming); + e.Request.Sizes = e.RequestSizes; + _requestFinishedImpl?.Invoke(this, e.Request); + e.Page?.FireRequestFinished(e.Request); + e.Response?.ReportFinished(); + break; + } + case "requestFailed": + { + var e = serverParams?.ToObject(_connection.DefaultJsonSerializerOptions); + e.Request.Failure = e.FailureText; + e.Request.SetResponseEndTiming(e.ResponseEndTiming); + _requestFailedImpl?.Invoke(this, e.Request); + e.Page?.FireRequestFailed(e.Request); + e.Response?.ReportFinished(e.FailureText); + } + break; + case "response": + { + var e = serverParams?.ToObject(_connection.DefaultJsonSerializerOptions); + _responseImpl?.Invoke(this, e.Response); + e.Page?.FireResponse(e.Response); + } + break; + } + } + + internal void OnDialog(IDialog dialog) + { + bool hasListeners = _dialogImpl?.GetInvocationList().Length > 0 || ((dialog?.Page as Page)?.HasDialogListenersAttached() ?? false); + if (!hasListeners) + { + // Although we do similar handling on the server side, we still need this logic + // on the client side due to a possible race condition between two async calls: + // a) removing "dialog" listener subscription (client->server) + // b) actual "dialog" event (server->client) + if ("beforeunload".Equals(dialog.Type, StringComparison.Ordinal)) + { + dialog.AcceptAsync().IgnoreException(); + } + else + { + dialog.DismissAsync().IgnoreException(); + } + } + else + { + _dialogImpl?.Invoke(this, dialog); + (dialog.Page as Page)?.FireDialog(dialog); + } + } + [MethodImpl(MethodImplOptions.NoInlining)] public Task AddCookiesAsync(IEnumerable cookies) => Channel.AddCookiesAsync(cookies); @@ -637,7 +671,7 @@ private void Channel_OnPage(object sender, PageChannel pageChannel) } } - private void Channel_BindingCall(object sender, BindingCall bindingCall) + private void Channel_BindingCall(BindingCall bindingCall) { if (_bindings.TryGetValue(bindingCall.Name, out var binding)) { diff --git a/src/Playwright/Core/CDPSession.cs b/src/Playwright/Core/CDPSession.cs index b4dc05c773..67eede5e9b 100644 --- a/src/Playwright/Core/CDPSession.cs +++ b/src/Playwright/Core/CDPSession.cs @@ -41,14 +41,17 @@ internal class CDPSession : ChannelOwnerBase, ICDPSession, IChannelOwner _channel; IChannel IChannelOwner.Channel => _channel; + internal override void OnMessage(string method, JsonElement? serverParams) + { + OnCDPEvent(serverParams!.Value.GetProperty("method").ToString(), serverParams.Value.GetProperty("params")); + } + [MethodImpl(MethodImplOptions.NoInlining)] public Task DetachAsync() => _channel.DetachAsync(); @@ -56,11 +59,11 @@ public CDPSession(IChannelOwner parent, string guid) : base(parent, guid) public Task SendAsync(string method, Dictionary? args = null) => _channel.SendAsync(method, args); - private void OnCDPEvent(object sender, (string Name, JsonElement? Params) @event) + private void OnCDPEvent(string name, JsonElement? @params) { - if (_cdpSessionEvents.TryGetValue(@event.Name, out var cdpNamedEvent)) + if (_cdpSessionEvents.TryGetValue(name, out var cdpNamedEvent)) { - cdpNamedEvent.RaiseEvent(@event.Params); + cdpNamedEvent.RaiseEvent(@params); } } diff --git a/src/Playwright/Core/ElementHandle.cs b/src/Playwright/Core/ElementHandle.cs index 4d3657b7ff..b346d2f901 100644 --- a/src/Playwright/Core/ElementHandle.cs +++ b/src/Playwright/Core/ElementHandle.cs @@ -41,7 +41,6 @@ internal class ElementHandle : JSHandle, IElementHandle, IChannelOwner Preview = newPreview; } ChannelBase IChannelOwner.Channel => _channel; @@ -50,6 +49,16 @@ internal ElementHandle(IChannelOwner parent, string guid, ElementHandleInitializ internal IChannel ElementChannel => _channel; + internal override void OnMessage(string method, JsonElement? serverParams) + { + switch (method) + { + case "previewUpdated": + Preview = serverParams.Value.GetProperty("preview").ToString(); + break; + } + } + public async Task WaitForSelectorAsync(string selector, ElementHandleWaitForSelectorOptions options = default) => (await _channel.WaitForSelectorAsync( selector: selector, diff --git a/src/Playwright/Core/Frame.cs b/src/Playwright/Core/Frame.cs index c7924cd741..ae2aeab0df 100644 --- a/src/Playwright/Core/Frame.cs +++ b/src/Playwright/Core/Frame.cs @@ -52,40 +52,6 @@ internal Frame(IChannelOwner parent, string guid, FrameInitializer initializer) Name = initializer.Name; ParentFrame = initializer.ParentFrame; _loadStates = initializer.LoadStates; - - _channel.LoadState += (_, e) => - { - if (e.Add.HasValue) - { - _loadStates.Add(e.Add.Value); - LoadState?.Invoke(this, e.Add.Value); - } - - if (e.Remove.HasValue) - { - _loadStates.Remove(e.Remove.Value); - } - if (this.ParentFrame == null && e.Add == WaitUntilState.Load && this.Page != null) - { - (this.Page as Page).FireLoad(); - } - if (this.ParentFrame == null && e.Add == WaitUntilState.DOMContentLoaded && this.Page != null) - { - (this.Page as Page).FireDOMContentLoaded(); - } - }; - - _channel.Navigated += (_, e) => - { - Url = e.Url; - Name = e.Name; - Navigated?.Invoke(this, e); - - if (string.IsNullOrEmpty(e.Error)) - { - ((Page)Page)?.OnFrameNavigated(this); - } - }; } /// @@ -116,6 +82,70 @@ internal Frame(IChannelOwner parent, string guid, FrameInitializer initializer) public bool IsDetached { get; internal set; } + internal override void OnMessage(string method, JsonElement? serverParams) + { + switch (method) + { + case "navigated": + var e = serverParams?.ToObject(_connection.DefaultJsonSerializerOptions); + + if (serverParams.Value.TryGetProperty("newDocument", out var documentElement)) + { + e.NewDocument = documentElement.ToObject(_connection.DefaultJsonSerializerOptions); + } + + OnNavigated(e); + break; + case "loadstate": + WaitUntilState? add = null; + WaitUntilState? remove = null; + if (serverParams.Value.TryGetProperty("add", out var addElement)) + { + add = addElement.ToObject(_connection.DefaultJsonSerializerOptions); + } + if (serverParams.Value.TryGetProperty("remove", out var removeElement)) + { + remove = removeElement.ToObject(_connection.DefaultJsonSerializerOptions); + } + OnLoadState(add, remove); + break; + } + } + + internal void OnLoadState(WaitUntilState? add, WaitUntilState? remove) + { + if (add.HasValue) + { + _loadStates.Add(add.Value); + LoadState?.Invoke(this, add.Value); + } + + if (remove.HasValue) + { + _loadStates.Remove(remove.Value); + } + if (this.ParentFrame == null && add == WaitUntilState.Load && this.Page != null) + { + (this.Page as Page).FireLoad(); + } + if (this.ParentFrame == null && add == WaitUntilState.DOMContentLoaded && this.Page != null) + { + (this.Page as Page).FireDOMContentLoaded(); + } + } + + internal void OnNavigated(FrameNavigatedEventArgs e) + { + Url = e.Url; + Name = e.Name; + Navigated?.Invoke(this, e); + + if (string.IsNullOrEmpty(e.Error)) + { + ((Page)Page)?.OnFrameNavigated(this); + } + } + [MethodImpl(MethodImplOptions.NoInlining)] public async Task FrameElementAsync() => (await _channel.FrameElementAsync().ConfigureAwait(false)).Object; diff --git a/src/Playwright/Core/JsonPipe.cs b/src/Playwright/Core/JsonPipe.cs index 77db51dad7..2803634472 100644 --- a/src/Playwright/Core/JsonPipe.cs +++ b/src/Playwright/Core/JsonPipe.cs @@ -24,7 +24,9 @@ using System; using System.Runtime.CompilerServices; +using System.Text.Json; using System.Threading.Tasks; +using Microsoft.Playwright.Helpers; using Microsoft.Playwright.Transport; using Microsoft.Playwright.Transport.Channels; using Microsoft.Playwright.Transport.Protocol; @@ -40,8 +42,6 @@ public JsonPipe(IChannelOwner parent, string guid, JsonPipeInitializer initializ { _channel = new(guid, parent.Connection, this); _initializer = initializer; - _channel.Closed += (_, e) => Closed.Invoke(this, e); - _channel.Message += (_, e) => Message.Invoke(this, e); } public event EventHandler Message; @@ -52,6 +52,26 @@ public JsonPipe(IChannelOwner parent, string guid, JsonPipeInitializer initializ IChannel IChannelOwner.Channel => _channel; + internal override void OnMessage(string method, JsonElement? serverParams) + { + switch (method) + { + case "closed": + if (serverParams.Value.TryGetProperty("error", out var error)) + { + Closed?.Invoke(this, error.ToObject(_connection.DefaultJsonSerializerOptions)); + } + else + { + Closed?.Invoke(this, null); + } + break; + case "message": + Message?.Invoke(this, serverParams?.GetProperty("message").ToObject(_connection.DefaultJsonSerializerOptions)); + break; + } + } + [MethodImpl(MethodImplOptions.NoInlining)] public Task CloseAsync() => _channel.CloseAsync(); diff --git a/src/Playwright/Core/Page.cs b/src/Playwright/Core/Page.cs index 01370e2fd4..6925351130 100644 --- a/src/Playwright/Core/Page.cs +++ b/src/Playwright/Core/Page.cs @@ -76,24 +76,6 @@ internal Page(IChannelOwner parent, string guid, PageInitializer initializer) : _touchscreen = new Touchscreen(_channel); _mouse = new Mouse(_channel); APIRequest = Context._request; - _channel.Closed += (_, _) => OnClose(); - _channel.Crashed += Channel_Crashed; - _channel.Popup += (_, page) => Popup?.Invoke(this, page); - _channel.WebSocket += (_, e) => WebSocket?.Invoke(this, e); - _channel.BindingCall += Channel_BindingCall; - _channel.Route += Channel_Route; - _channel.FrameAttached += Channel_FrameAttached; - _channel.FrameDetached += Channel_FrameDetached; - _channel.Download += (_, e) => Download?.Invoke(this, new Download(this, e.Url, e.SuggestedFilename, e.Artifact.Object)); - _channel.Video += (_, artifact) => ForceVideo().ArtifactReady(artifact); - - _channel.FileChooser += (_, e) => _fileChooserImpl?.Invoke(this, new FileChooser(this, e.Element.Object, e.IsMultiple)); - _channel.Worker += (_, worker) => - { - _workers.Add(worker); - worker.Page = this; - Worker?.Invoke(this, worker); - }; _initializer = initializer; @@ -251,6 +233,55 @@ public IVideo Video public IAPIRequestContext APIRequest { get; } + internal override void OnMessage(string method, JsonElement? serverParams) + { + switch (method) + { + case "close": + OnClose(); + break; + case "crash": + Channel_Crashed(); + break; + case "bindingCall": + Channel_BindingCall( + this, + serverParams?.GetProperty("binding").ToObject(_connection.DefaultJsonSerializerOptions).Object); + break; + case "route": + var route = serverParams?.GetProperty("route").ToObject(_connection.DefaultJsonSerializerOptions).Object; + Channel_Route(this, route); + break; + case "popup": + Popup?.Invoke(this, serverParams?.GetProperty("page").ToObject(_connection.DefaultJsonSerializerOptions).Object); + break; + case "fileChooser": + _fileChooserImpl?.Invoke(this, new FileChooser(this, serverParams.Value.GetProperty("element").ToObject(_connection.DefaultJsonSerializerOptions).Object, serverParams.Value.GetProperty("isMultiple").ToObject(_connection.DefaultJsonSerializerOptions))); + break; + case "frameAttached": + Channel_FrameAttached(this, serverParams?.GetProperty("frame").ToObject(_connection.DefaultJsonSerializerOptions).Object); + break; + case "frameDetached": + Channel_FrameDetached(this, serverParams?.GetProperty("frame").ToObject(_connection.DefaultJsonSerializerOptions).Object); + break; + case "webSocket": + WebSocket?.Invoke(this, serverParams?.GetProperty("webSocket").ToObject(_connection.DefaultJsonSerializerOptions).Object); + break; + case "download": + Download?.Invoke(this, new Download(this, serverParams.Value.GetProperty("url").ToObject(_connection.DefaultJsonSerializerOptions), serverParams.Value.GetProperty("suggestedFilename").ToObject(_connection.DefaultJsonSerializerOptions), serverParams.Value.GetProperty("artifact").ToObject(_connection.DefaultJsonSerializerOptions).Object)); + break; + case "video": + ForceVideo().ArtifactReady(serverParams?.GetProperty("artifact").ToObject(_connection.DefaultJsonSerializerOptions).Object); + break; + case "worker": + var worker = serverParams?.GetProperty("worker").ToObject(_connection.DefaultJsonSerializerOptions).Object; + _workers.Add(worker); + worker.Page = this; + Worker?.Invoke(this, worker); + break; + } + } + [MethodImpl(MethodImplOptions.NoInlining)] public IFrame Frame(string name) => Frames.FirstOrDefault(f => f.Name == name); @@ -1188,7 +1219,7 @@ internal void OnClose() Close?.Invoke(this, this); } - private void Channel_Crashed(object sender, EventArgs e) + private void Channel_Crashed() { Crash?.Invoke(this, this); } diff --git a/src/Playwright/Core/WebSocket.cs b/src/Playwright/Core/WebSocket.cs index a673595b97..43f3020930 100644 --- a/src/Playwright/Core/WebSocket.cs +++ b/src/Playwright/Core/WebSocket.cs @@ -23,6 +23,8 @@ */ using System; +using System.Text.Json; +using Microsoft.Playwright.Helpers; using Microsoft.Playwright.Transport; using Microsoft.Playwright.Transport.Channels; using Microsoft.Playwright.Transport.Protocol; @@ -31,6 +33,7 @@ namespace Microsoft.Playwright.Core; internal class WebSocket : ChannelOwnerBase, IChannelOwner, IWebSocket { + private const int OpcodeBase64 = 2; private readonly WebSocketChannel _channel; private readonly WebSocketInitializer _initializer; @@ -38,15 +41,6 @@ internal WebSocket(IChannelOwner parent, string guid, WebSocketInitializer initi { _channel = new(guid, parent.Connection, this); _initializer = initializer; - - _channel.Close += (_, _) => - { - IsClosed = true; - Close?.Invoke(this, this); - }; - _channel.FrameReceived += (_, e) => FrameReceived?.Invoke(this, e); - _channel.FrameSent += (_, e) => FrameSent?.Invoke(this, e); - _channel.SocketError += (_, e) => SocketError?.Invoke(this, e); } public event EventHandler Close; @@ -64,4 +58,48 @@ internal WebSocket(IChannelOwner parent, string guid, WebSocketInitializer initi public string Url => _initializer.Url; public bool IsClosed { get; internal set; } + + internal override void OnMessage(string method, JsonElement? serverParams) + { + bool IsTextOrBinaryFrame(out int opcode) + { + opcode = serverParams?.GetProperty("opcode").ToObject() ?? 0; + return opcode != 1 && opcode != 2; + } + + int opcode; + switch (method) + { + case "close": + IsClosed = true; + Close?.Invoke(this, this); + break; + case "frameSent": + if (IsTextOrBinaryFrame(out opcode)) + { + break; + } + + FrameSent?.Invoke( + this, + new WebSocketFrame( + serverParams?.GetProperty("data").ToObject(), + opcode == OpcodeBase64)); + break; + case "frameReceived": + if (IsTextOrBinaryFrame(out opcode)) + { + break; + } + FrameReceived?.Invoke( + this, + new WebSocketFrame( + serverParams?.GetProperty("data").ToObject(), + opcode == OpcodeBase64)); + break; + case "socketError": + SocketError?.Invoke(this, serverParams?.GetProperty("error").ToObject()); + break; + } + } } diff --git a/src/Playwright/Core/Worker.cs b/src/Playwright/Core/Worker.cs index c6863d07ad..b7f459bf91 100644 --- a/src/Playwright/Core/Worker.cs +++ b/src/Playwright/Core/Worker.cs @@ -24,6 +24,7 @@ using System; using System.Runtime.CompilerServices; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.Playwright.Helpers; using Microsoft.Playwright.Transport; @@ -41,22 +42,6 @@ public Worker(IChannelOwner parent, string guid, WorkerInitializer initializer) { _channel = new(guid, parent.Connection, this); _initializer = initializer; - - _channel.Close += (_, _) => - { - if (Page != null) - { - Page._workers.Remove(this); - } - - if (Context != null) - { - Context._serviceWorkers.Remove(this); - } - - Close?.Invoke(this, this); - ClosedTcs.SetResult(true); - }; } public event EventHandler Close; @@ -73,6 +58,32 @@ public Worker(IChannelOwner parent, string guid, WorkerInitializer initializer) internal TaskCompletionSource ClosedTcs { get; } = new(); + internal override void OnMessage(string method, JsonElement? serverParams) + { + switch (method) + { + case "close": + OnClose(); + break; + } + } + + internal void OnClose() + { + if (Page != null) + { + Page._workers.Remove(this); + } + + if (Context != null) + { + Context._serviceWorkers.Remove(this); + } + + Close?.Invoke(this, this); + ClosedTcs.SetResult(true); + } + [MethodImpl(MethodImplOptions.NoInlining)] public async Task EvaluateAsync(string expression, object arg = null) => ScriptsHelper.ParseEvaluateResult(await _channel.EvaluateExpressionAsync( diff --git a/src/Playwright/Transport/ChannelOwnerBase.cs b/src/Playwright/Transport/ChannelOwnerBase.cs index 22b8e6b240..9c7d4fc929 100644 --- a/src/Playwright/Transport/ChannelOwnerBase.cs +++ b/src/Playwright/Transport/ChannelOwnerBase.cs @@ -26,6 +26,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Runtime.CompilerServices; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.Playwright.Helpers; using Microsoft.Playwright.Transport.Channels; @@ -69,6 +70,10 @@ internal ChannelOwnerBase(IChannelOwner parent, Connection connection, string gu internal IChannelOwner Parent { get; set; } + internal virtual void OnMessage(string method, JsonElement? serverParams) + { + } + void IChannelOwner.Adopt(ChannelOwnerBase child) { child.Parent.Objects.TryRemove(child.Guid, out _); diff --git a/src/Playwright/Transport/Channels/BrowserChannel.cs b/src/Playwright/Transport/Channels/BrowserChannel.cs index 15dd651407..4e6661fb96 100644 --- a/src/Playwright/Transport/Channels/BrowserChannel.cs +++ b/src/Playwright/Transport/Channels/BrowserChannel.cs @@ -22,7 +22,6 @@ * SOFTWARE. */ -using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -41,8 +40,6 @@ public BrowserChannel(string guid, Connection connection, Browser owner) : base( { } - internal event EventHandler Closed; - internal static Dictionary PrepareHarOptions( HarContentPolicy? recordHarContent, HarMode? recordHarMode, @@ -91,16 +88,6 @@ internal static Dictionary PrepareHarOptions( return null; } - internal override void OnMessage(string method, JsonElement? serverParams) - { - switch (method) - { - case "close": - Closed?.Invoke(this, EventArgs.Empty); - break; - } - } - internal Task NewBrowserCDPSessionAsync() => Connection.SendMessageToServerAsync( Object, diff --git a/src/Playwright/Transport/Channels/BrowserContextChannel.cs b/src/Playwright/Transport/Channels/BrowserContextChannel.cs index 8d4c2e2556..9d0a57c926 100644 --- a/src/Playwright/Transport/Channels/BrowserContextChannel.cs +++ b/src/Playwright/Transport/Channels/BrowserContextChannel.cs @@ -25,7 +25,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text.Json; using System.Text.RegularExpressions; using System.Threading.Tasks; using Microsoft.Playwright.Core; @@ -40,87 +39,6 @@ public BrowserContextChannel(string guid, Connection connection, BrowserContext { } - internal event EventHandler Close; - - internal event EventHandler Console; - - internal event EventHandler Dialog; - - internal event EventHandler Page; - - internal event EventHandler BackgroundPage; - - internal event EventHandler ServiceWorker; - - internal event EventHandler BindingCall; - - internal event EventHandler<(SerializedError Error, PageChannel Page)> PageError; - - internal event EventHandler Route; - - internal event EventHandler Request; - - internal event EventHandler RequestFinished; - - internal event EventHandler RequestFailed; - - internal event EventHandler Response; - - internal override void OnMessage(string method, JsonElement? serverParams) - { - switch (method) - { - case "close": - Close?.Invoke(this, EventArgs.Empty); - break; - case "bindingCall": - BindingCall?.Invoke( - this, - serverParams?.GetProperty("binding").ToObject(Connection.DefaultJsonSerializerOptions).Object); - break; - case "dialog": - Dialog?.Invoke(this, serverParams?.GetProperty("dialog").ToObject(Connection.DefaultJsonSerializerOptions).Object); - break; - case "console": - Console?.Invoke(this, serverParams?.ToObject(Connection.DefaultJsonSerializerOptions)); - break; - case "route": - var route = serverParams?.GetProperty("route").ToObject(Connection.DefaultJsonSerializerOptions).Object; - Route?.Invoke(this, route); - break; - case "page": - Page?.Invoke( - this, - serverParams?.GetProperty("page").ToObject(Connection.DefaultJsonSerializerOptions)); - break; - case "pageError": - PageError?.Invoke(this, new(serverParams?.GetProperty("error").ToObject(Connection.DefaultJsonSerializerOptions), serverParams?.GetProperty("page").ToObject(Connection.DefaultJsonSerializerOptions))); - break; - case "crBackgroundPage": - BackgroundPage?.Invoke( - this, - serverParams?.GetProperty("page").ToObject(Connection.DefaultJsonSerializerOptions)); - break; - case "serviceWorker": - ServiceWorker?.Invoke( - this, - serverParams?.GetProperty("worker").ToObject(Connection.DefaultJsonSerializerOptions).Object); - break; - case "request": - Request?.Invoke(this, serverParams?.ToObject(Connection.DefaultJsonSerializerOptions)); - break; - case "requestFinished": - RequestFinished?.Invoke(this, serverParams?.ToObject(Connection.DefaultJsonSerializerOptions)); - break; - case "requestFailed": - RequestFailed?.Invoke(this, serverParams?.ToObject(Connection.DefaultJsonSerializerOptions)); - break; - case "response": - Response?.Invoke(this, serverParams?.ToObject(Connection.DefaultJsonSerializerOptions)); - break; - } - } - internal Task NewCDPSessionAsync(Page page) => Connection.SendMessageToServerAsync( Object, diff --git a/src/Playwright/Transport/Channels/CDPChannel.cs b/src/Playwright/Transport/Channels/CDPChannel.cs index efd7a2407a..549a19a1e9 100644 --- a/src/Playwright/Transport/Channels/CDPChannel.cs +++ b/src/Playwright/Transport/Channels/CDPChannel.cs @@ -21,7 +21,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -using System; using System.Collections.Generic; using System.Text.Json; using System.Threading.Tasks; @@ -37,13 +36,6 @@ public CDPChannel(string guid, Connection connection, CDPSession owner) : base(g { } - internal event EventHandler<(string EventName, JsonElement? EventParams)>? CDPEvent; - - internal override void OnMessage(string method, JsonElement? serverParams) - { - CDPEvent?.Invoke(this, (serverParams!.Value.GetProperty("method").ToString(), serverParams.Value.GetProperty("params"))); - } - internal Task DetachAsync() { return Connection.SendMessageToServerAsync( diff --git a/src/Playwright/Transport/Channels/ChannelBase.cs b/src/Playwright/Transport/Channels/ChannelBase.cs index 9e3d40205e..0594da6938 100644 --- a/src/Playwright/Transport/Channels/ChannelBase.cs +++ b/src/Playwright/Transport/Channels/ChannelBase.cs @@ -22,8 +22,6 @@ * SOFTWARE. */ -using System.Text.Json; - namespace Microsoft.Playwright.Transport.Channels; internal class ChannelBase @@ -37,8 +35,4 @@ public ChannelBase(string guid, Connection connection) public string Guid { get; } public Connection Connection { get; } - - internal virtual void OnMessage(string method, JsonElement? serverParams) - { - } } diff --git a/src/Playwright/Transport/Channels/ElementHandleChannel.cs b/src/Playwright/Transport/Channels/ElementHandleChannel.cs index 08e3f79746..30f201ef69 100644 --- a/src/Playwright/Transport/Channels/ElementHandleChannel.cs +++ b/src/Playwright/Transport/Channels/ElementHandleChannel.cs @@ -22,7 +22,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -using System; using System.Collections.Generic; using System.Linq; using System.Text.Json; @@ -40,20 +39,8 @@ public ElementHandleChannel(string guid, Connection connection, ElementHandle ow Object = owner; } - internal event EventHandler PreviewUpdated; - public new ElementHandle Object { get; set; } - internal override void OnMessage(string method, JsonElement? serverParams) - { - switch (method) - { - case "previewUpdated": - PreviewUpdated?.Invoke(this, serverParams.Value.GetProperty("preview").ToString()); - break; - } - } - internal Task WaitForSelectorAsync(string selector, WaitForSelectorState? state, float? timeout, bool? strict) { var args = new Dictionary diff --git a/src/Playwright/Transport/Channels/FrameChannel.cs b/src/Playwright/Transport/Channels/FrameChannel.cs index 5ebf247e65..1764f495a8 100644 --- a/src/Playwright/Transport/Channels/FrameChannel.cs +++ b/src/Playwright/Transport/Channels/FrameChannel.cs @@ -22,7 +22,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -using System; using System.Collections.Generic; using System.Linq; using System.Text.Json; @@ -40,39 +39,6 @@ public FrameChannel(string guid, Connection connection, Frame owner) : base(guid { } - internal event EventHandler Navigated; - - internal event EventHandler<(WaitUntilState? Add, WaitUntilState? Remove)> LoadState; - - internal override void OnMessage(string method, JsonElement? serverParams) - { - switch (method) - { - case "navigated": - var e = serverParams?.ToObject(Connection.DefaultJsonSerializerOptions); - - if (serverParams.Value.TryGetProperty("newDocument", out var documentElement)) - { - e.NewDocument = documentElement.ToObject(Connection.DefaultJsonSerializerOptions); - } - - Navigated?.Invoke(this, e); - break; - case "loadstate": - WaitUntilState? add = null; - WaitUntilState? remove = null; - if (serverParams.Value.TryGetProperty("add", out var addElement)) - { - add = addElement.ToObject(Connection.DefaultJsonSerializerOptions); - } - if (serverParams.Value.TryGetProperty("remove", out var removeElement)) - { - remove = removeElement.ToObject(Connection.DefaultJsonSerializerOptions); - } - LoadState?.Invoke(this, (add, remove)); - break; - } - } internal Task QuerySelectorAsync(string selector, bool? strict) { diff --git a/src/Playwright/Transport/Channels/JsonPipeChannel.cs b/src/Playwright/Transport/Channels/JsonPipeChannel.cs index 2398cda6a0..b0c6a1e1bc 100644 --- a/src/Playwright/Transport/Channels/JsonPipeChannel.cs +++ b/src/Playwright/Transport/Channels/JsonPipeChannel.cs @@ -22,13 +22,9 @@ * SOFTWARE. */ -using System; using System.Collections.Generic; -using System.Text.Json; using System.Threading.Tasks; using Microsoft.Playwright.Core; -using Microsoft.Playwright.Helpers; -using Microsoft.Playwright.Transport.Protocol; namespace Microsoft.Playwright.Transport.Channels; @@ -38,30 +34,6 @@ public JsonPipeChannel(string guid, Connection connection, JsonPipe owner) : bas { } - public event EventHandler Message; - - public event EventHandler Closed; - - internal override void OnMessage(string method, JsonElement? serverParams) - { - switch (method) - { - case "closed": - if (serverParams.Value.TryGetProperty("error", out var error)) - { - Closed?.Invoke(this, error.ToObject(Connection.DefaultJsonSerializerOptions)); - } - else - { - Closed?.Invoke(this, null); - } - break; - case "message": - Message?.Invoke(this, serverParams?.GetProperty("message").ToObject(Connection.DefaultJsonSerializerOptions)); - break; - } - } - internal Task SendAsync(object message) => Connection.SendMessageToServerAsync(Object, "send", new Dictionary { diff --git a/src/Playwright/Transport/Channels/PageChannel.cs b/src/Playwright/Transport/Channels/PageChannel.cs index 120492c52a..ab7ac38c64 100644 --- a/src/Playwright/Transport/Channels/PageChannel.cs +++ b/src/Playwright/Transport/Channels/PageChannel.cs @@ -22,13 +22,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -using System; using System.Collections.Generic; using System.Linq; using System.Text.Json; using System.Threading.Tasks; using Microsoft.Playwright.Core; -using Microsoft.Playwright.Helpers; using Microsoft.Playwright.Transport.Protocol; namespace Microsoft.Playwright.Transport.Channels; @@ -39,78 +37,6 @@ public PageChannel(string guid, Connection connection, Page owner) : base(guid, { } - internal event EventHandler Closed; - - internal event EventHandler Crashed; - - internal event EventHandler WebSocket; - - internal event EventHandler Popup; - - internal event EventHandler BindingCall; - - internal event EventHandler Route; - - internal event EventHandler