From af833048fd97791275949633d94f9390c5e9c269 Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Sun, 4 Aug 2024 19:15:27 -0500 Subject: [PATCH] UseExistingPage --- .../Browsing/IWebBrowser.cs | 2 +- .../Browsing/Models/PageActionArgs.cs | 5 ++ .../PlaywrightDriver/PlaywrightInstance.cs | 46 +++++++++++++- .../PlaywrightWebDriver.GoToPage.cs | 60 +++---------------- .../PlaywrightDriver/PlaywrightWebDriver.cs | 6 +- 5 files changed, 63 insertions(+), 56 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Browsing/IWebBrowser.cs b/src/Infrastructure/BotSharp.Abstraction/Browsing/IWebBrowser.cs index d81dae39..ea80e81a 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Browsing/IWebBrowser.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Browsing/IWebBrowser.cs @@ -4,7 +4,7 @@ namespace BotSharp.Abstraction.Browsing; public interface IWebBrowser { - void SetServiceProvider(IServiceProvider services); + void SetServiceProvider (IServiceProvider services); Task LaunchBrowser(MessageInfo message, BrowserActionArgs args); Task ScreenshotAsync(MessageInfo message, string path); Task ScrollPage(MessageInfo message, PageActionArgs args); diff --git a/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/PageActionArgs.cs b/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/PageActionArgs.cs index 0819520d..661b0da4 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/PageActionArgs.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Browsing/Models/PageActionArgs.cs @@ -10,7 +10,12 @@ public class PageActionArgs public string? Direction { get; set; } public string Url { get; set; } = null!; + + /// + /// This value has to be set to true if you want to get the page XHR/ Fetch responses + /// public bool OpenNewTab { get; set; } = false; + public bool UseExistingPage { get; set; } = false; public bool WaitForNetworkIdle { get; set; } = true; public float? Timeout { get; set; } diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs index 53466f1a..79eec038 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightInstance.cs @@ -5,6 +5,8 @@ namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver; public class PlaywrightInstance : IDisposable { IPlaywright _playwright; + IServiceProvider _services; + public IServiceProvider Services => _services; Dictionary _contexts = new Dictionary(); Dictionary> _pages = new Dictionary>(); @@ -18,6 +20,11 @@ public class PlaywrightInstance : IDisposable /// public Dictionary> Pages => _pages; + public void SetServiceProvider(IServiceProvider services) + { + _services = services; + } + public IPage GetPage(string contextId, string? pattern = null) { if (string.IsNullOrEmpty(pattern)) @@ -106,7 +113,7 @@ public class PlaywrightInstance : IDisposable return _contexts[ctxId]; } - public async Task NewPage(MessageInfo message, IServiceProvider services) + public async Task NewPage(MessageInfo message) { var context = await GetContext(message.ContextId); var page = await context.NewPageAsync(); @@ -116,6 +123,43 @@ public class PlaywrightInstance : IDisposable var js = @"Object.defineProperties(navigator, {webdriver:{get:()=>false}});"; await page.AddInitScriptAsync(js); + page.Response += async (sender, e) => + { + if (e.Status != 204 && + e.Headers.ContainsKey("content-type") && + e.Headers["content-type"].Contains("application/json") && + (e.Request.ResourceType == "fetch" || e.Request.ResourceType == "xhr")) + { + Serilog.Log.Information($"{e.Request.Method}: {e.Url}"); + JsonElement? json = null; + try + { + if (e.Status == 200 && e.Ok) + { + json = await e.JsonAsync(); + } + else + { + Serilog.Log.Warning($"Response status: {e.Status} {e.StatusText}, OK: {e.Ok}"); + } + + var webPageResponseHooks = _services.GetServices(); + foreach (var hook in webPageResponseHooks) + { + hook.OnDataFetched(message, e.Url.ToLower(), e.Request?.PostData ?? string.Empty, JsonSerializer.Serialize(json)); + } + } + catch (ObjectDisposedException ex) + { + Serilog.Log.Information(ex.Message); + } + catch (Exception ex) + { + Serilog.Log.Error(ex.ToString()); + } + } + }; + return page; } diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GoToPage.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GoToPage.cs index 4b8cc5b1..76e63171 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GoToPage.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.GoToPage.cs @@ -8,58 +8,11 @@ public partial class PlaywrightWebDriver var context = await _instance.GetContext(message.ContextId); try { - // Check if the page is already open - /*if (!args.OpenNewTab && context.Pages.Count > 0) - { - foreach (var p in context.Pages) - { - if (p.Url == args.Url) - { - // Disable this due to performance issue, some page is too large - // result.Body = await p.ContentAsync(); - result.IsSuccess = true; - // await p.BringToFrontAsync(); - return result; - } - } - }*/ + var page = args.UseExistingPage ? + _instance.GetPage(message.ContextId, pattern: args.Url) : + await _instance.NewPage(message); - var page = args.OpenNewTab ? await _instance.NewPage(message, _services) : - _instance.GetPage(message.ContextId, pattern: args.Url); - - page.Response += async (sender, e) => - { - if (e.Headers.ContainsKey("content-type") && - e.Headers["content-type"].Contains("application/json") && - (e.Request.ResourceType == "fetch" || e.Request.ResourceType == "xhr")) - { - Serilog.Log.Information($"{e.Request.Method}: {e.Url}"); - JsonElement? json = null; - try - { - if (e.Status == 200 && e.Ok) - { - json = await e.JsonAsync(); - } - else - { - Serilog.Log.Warning($"Response status: {e.Status} {e.StatusText}, OK: {e.Ok}"); - } - - var webPageResponseHooks = _services.GetServices(); - foreach (var hook in webPageResponseHooks) - { - hook.OnDataFetched(message, e.Url.ToLower(), e.Request?.PostData ?? string.Empty, JsonSerializer.Serialize(json)); - } - } - catch (Exception ex) - { - Serilog.Log.Error(ex.ToString()); - } - } - }; - - if (!args.OpenNewTab && page != null && page.Url != "about:blank") + if (args.UseExistingPage && page != null && page.Url != "about:blank") { Serilog.Log.Information($"goto existing page: {args.Url}"); result.IsSuccess = true; @@ -68,6 +21,11 @@ public partial class PlaywrightWebDriver Serilog.Log.Information($"goto page: {args.Url}"); + if (args.UseExistingPage && args.OpenNewTab && page != null && page.Url == "about:blank") + { + page = await _instance.NewPage(message); + } + var response = await page.GotoAsync(args.Url, new PageGotoOptions { Timeout = args.Timeout diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.cs index cd0b7769..88a10485 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Drivers/PlaywrightDriver/PlaywrightWebDriver.cs @@ -2,7 +2,7 @@ namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver; public partial class PlaywrightWebDriver : IWebBrowser { - private IServiceProvider _services; + private IServiceProvider _services => _instance.Services; private readonly PlaywrightInstance _instance; private readonly ILogger _logger; public PlaywrightInstance Instance => _instance; @@ -12,9 +12,9 @@ public partial class PlaywrightWebDriver : IWebBrowser public PlaywrightWebDriver(IServiceProvider services, PlaywrightInstance instance, ILogger logger) { - _services = services; _instance = instance; _logger = logger; + _instance.SetServiceProvider(services); } public void SetAgent(Agent agent) @@ -66,6 +66,6 @@ public partial class PlaywrightWebDriver : IWebBrowser public void SetServiceProvider(IServiceProvider services) { - _services = services; + _instance.SetServiceProvider(_services); } }