Skip to content

Optimize WebDriver with context id. #411

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 12, 2024
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
13 changes: 7 additions & 6 deletions src/Infrastructure/BotSharp.Abstraction/Browsing/IWebBrowser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ namespace BotSharp.Abstraction.Browsing;

public interface IWebBrowser
{
Task<BrowserActionResult> LaunchBrowser(string conversationId, string? url);
Task<BrowserActionResult> ScreenshotAsync(string conversationId, string path);
Task<BrowserActionResult> LaunchBrowser(string contextId, string? url, bool openIfNotExist = true);
Task<BrowserActionResult> ScreenshotAsync(string contextId, string path);
Task<BrowserActionResult> ScrollPageAsync(BrowserActionParams actionParams);

Task<BrowserActionResult> ActionOnElement(MessageInfo message, ElementLocatingArgs location, ElementActionArgs action);
Expand All @@ -19,10 +19,11 @@ public interface IWebBrowser
Task<BrowserActionResult> ChangeListValue(BrowserActionParams actionParams);
Task<BrowserActionResult> CheckRadioButton(BrowserActionParams actionParams);
Task<BrowserActionResult> ChangeCheckbox(BrowserActionParams actionParams);
Task<BrowserActionResult> GoToPage(string conversationId, string url);
Task<BrowserActionResult> GoToPage(string contextId, string url, bool openNewTab = false);
Task<string> ExtractData(BrowserActionParams actionParams);
Task<T> EvaluateScript<T>(string conversationId, string script);
Task CloseBrowser(string conversationId);
Task<BrowserActionResult> SendHttpRequest(HttpRequestParams actionParams);
Task<T> EvaluateScript<T>(string contextId, string script);
Task CloseBrowser(string contextId);
Task CloseCurrentPage(string contextId);
Task<BrowserActionResult> SendHttpRequest(string contextId, HttpRequestParams actionParams);
Task<string> GetAttributeValue(MessageInfo message, ElementLocatingArgs location, BrowserActionResult result);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ public class BrowserActionParams
{
public Agent Agent { get; set; }
public BrowsingContextIn Context { get; set; }
public string ConversationId { get; set; }
public string ContextId { get; set; }
public string MessageId { get; set; }

public BrowserActionParams(Agent agent, BrowsingContextIn context, string conversationId, string messageId)
public BrowserActionParams(Agent agent, BrowsingContextIn context, string contextId, string messageId)
{
Agent = agent;
Context = context;
ConversationId = conversationId;
ContextId = contextId;
MessageId = messageId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ namespace BotSharp.Abstraction.Browsing.Models;
public class MessageInfo
{
public string AgentId { get; set; }
public string ConversationId { get; set; }
public string ContextId { get; set; }
public string MessageId { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,30 @@ public class PlaywrightInstance : IDisposable
{
IPlaywright _playwright;
Dictionary<string, IBrowserContext> _contexts = new Dictionary<string, IBrowserContext>();
public Dictionary<string, IBrowserContext> Contexts => _contexts;

public IPage GetPage(string id)
{
InitInstance(id).Wait();
return _contexts[id].Pages.LastOrDefault();
}

public async Task InitInstance(string id)
public async Task<IBrowserContext> InitInstance(string id)
{
if (_playwright == null)
{
_playwright = await Playwright.CreateAsync();
}
await InitContext(id);
return await InitContext(id);
}

public async Task InitContext(string id)
public async Task<IBrowserContext> InitContext(string id)
{
if (_contexts.ContainsKey(id))
return;
#if DEBUG
string tempFolderPath = $"{Path.GetTempPath()}\\playwright";
#else
return _contexts[id];

string tempFolderPath = $"{Path.GetTempPath()}\\playwright\\{id}";
#endif

_contexts[id] = await _playwright.Chromium.LaunchPersistentContextAsync(tempFolderPath, new BrowserTypeLaunchPersistentContextOptions
{
#if DEBUG
Expand Down Expand Up @@ -65,6 +64,8 @@ public async Task InitContext(string id)
Serilog.Log.Warning($"Playwright browser context is closed");
_contexts.Remove(id);
};

return _contexts[id];
}

public async Task<IPage> NewPage(string id)
Expand Down Expand Up @@ -92,6 +93,14 @@ public async Task Close(string id)
}
}

public async Task CloseCurrentPage(string id)
{
if (_contexts.ContainsKey(id))
{
await GetPage(id).CloseAsync();
}
}

public void Dispose()
{
_contexts.Clear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public partial class PlaywrightWebDriver
{
public async Task<BrowserActionResult> ActionOnElement(MessageInfo message, ElementLocatingArgs location, ElementActionArgs action)
{
await _instance.Wait(message.ConversationId);
await _instance.Wait(message.ContextId);
var result = await LocateElement(message, location);
if (result.IsSuccess)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System.Text.RegularExpressions;

namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;

public partial class PlaywrightWebDriver
Expand All @@ -8,7 +6,7 @@ public async Task<BrowserActionResult> ChangeCheckbox(BrowserActionParams action
{
var result = new BrowserActionResult();

await _instance.Wait(actionParams.ConversationId);
await _instance.Wait(actionParams.ContextId);

// Retrieve the page raw html and infer the element path
var regexExpression = actionParams.Context.MatchRule.ToLower() switch
Expand All @@ -19,7 +17,7 @@ public async Task<BrowserActionResult> ChangeCheckbox(BrowserActionParams action
_ => $"^{actionParams.Context.ElementText}$"
};
var regex = new Regex(regexExpression, RegexOptions.IgnoreCase);
var elements = _instance.GetPage(actionParams.ConversationId).GetByText(regex);
var elements = _instance.GetPage(actionParams.ContextId).GetByText(regex);
var count = await elements.CountAsync();

var errorMessage = $"Can't locate element by keyword {actionParams.Context.ElementText}";
Expand Down Expand Up @@ -55,7 +53,7 @@ public async Task<BrowserActionResult> ChangeCheckbox(BrowserActionParams action
}
else
{
elements = _instance.GetPage(actionParams.ConversationId).Locator($"#{id}");
elements = _instance.GetPage(actionParams.ContextId).Locator($"#{id}");
}
count = await elements.CountAsync();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ public partial class PlaywrightWebDriver
public async Task<BrowserActionResult> ChangeListValue(BrowserActionParams actionParams)
{
var result = new BrowserActionResult();
await _instance.Wait(actionParams.ConversationId);
await _instance.Wait(actionParams.ContextId);

// Retrieve the page raw html and infer the element path
var body = await _instance.GetPage(actionParams.ConversationId).QuerySelectorAsync("body");
var body = await _instance.GetPage(actionParams.ContextId).QuerySelectorAsync("body");

var str = new List<string>();
var inputs = await body.QuerySelectorAllAsync("select");
Expand Down Expand Up @@ -61,7 +61,7 @@ public async Task<BrowserActionResult> ChangeListValue(BrowserActionParams actio
string.Join("", str),
actionParams.Context.ElementName,
actionParams.MessageId);
ILocator element = Locator(actionParams.ConversationId, htmlElementContextOut);
ILocator? element = Locator(actionParams.ContextId, htmlElementContextOut);

try
{
Expand All @@ -70,11 +70,11 @@ public async Task<BrowserActionResult> ChangeListValue(BrowserActionParams actio
if (!isVisible)
{
// Select the element you want to make visible (replace with your own selector)
var control = await _instance.GetPage(actionParams.ConversationId)
var control = await _instance.GetPage(actionParams.ContextId)
.QuerySelectorAsync($"#{htmlElementContextOut.ElementId}");

// Show the element by modifying its CSS styles
await _instance.GetPage(actionParams.ConversationId)
await _instance.GetPage(actionParams.ContextId)
.EvaluateAsync(@"(element) => {
element.style.display = 'block';
element.style.visibility = 'visible';
Expand All @@ -92,11 +92,11 @@ await element.SelectOptionAsync(new SelectOptionValue
if (!isVisible)
{
// Select the element you want to make visible (replace with your own selector)
var control = await _instance.GetPage(actionParams.ConversationId)
var control = await _instance.GetPage(actionParams.ContextId)
.QuerySelectorAsync($"#{htmlElementContextOut.ElementId}");

// Show the element by modifying its CSS styles
await _instance.GetPage(actionParams.ConversationId).EvaluateAsync(@"(element) => {
await _instance.GetPage(actionParams.ContextId).EvaluateAsync(@"(element) => {
element.style.display = 'none';
element.style.visibility = 'hidden';
}", control);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ public partial class PlaywrightWebDriver
public async Task<BrowserActionResult> CheckRadioButton(BrowserActionParams actionParams)
{
var result = new BrowserActionResult();
await _instance.Wait(actionParams.ConversationId);
await _instance.Wait(actionParams.ContextId);

// Retrieve the page raw html and infer the element path
var regexExpression = actionParams.Context.MatchRule.ToLower() switch
Expand All @@ -16,7 +16,7 @@ public async Task<BrowserActionResult> CheckRadioButton(BrowserActionParams acti
_ => $"^{actionParams.Context.ElementText}$"
};
var regex = new Regex(regexExpression, RegexOptions.IgnoreCase);
var elements = _instance.GetPage(actionParams.ConversationId).GetByText(regex);
var elements = _instance.GetPage(actionParams.ContextId).GetByText(regex);
var count = await elements.CountAsync();

var errorMessage = $"Can't locate element by keyword {actionParams.Context.ElementText}";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ public partial class PlaywrightWebDriver
public async Task<BrowserActionResult> ClickButton(BrowserActionParams actionParams)
{
var result = new BrowserActionResult();
await _instance.Wait(actionParams.ConversationId);
await _instance.Wait(actionParams.ContextId);

// Find by text exactly match
var elements = _instance.GetPage(actionParams.ConversationId)
var elements = _instance.GetPage(actionParams.ContextId)
.GetByRole(AriaRole.Button, new PageGetByRoleOptions
{
Name = actionParams.Context.ElementName
Expand All @@ -17,7 +17,7 @@ public async Task<BrowserActionResult> ClickButton(BrowserActionParams actionPar

if (count == 0)
{
elements = _instance.GetPage(actionParams.ConversationId)
elements = _instance.GetPage(actionParams.ContextId)
.GetByRole(AriaRole.Link, new PageGetByRoleOptions
{
Name = actionParams.Context.ElementName
Expand All @@ -27,7 +27,7 @@ public async Task<BrowserActionResult> ClickButton(BrowserActionParams actionPar

if (count == 0)
{
elements = _instance.GetPage(actionParams.ConversationId)
elements = _instance.GetPage(actionParams.ContextId)
.GetByText(actionParams.Context.ElementName);
count = await elements.CountAsync();
}
Expand All @@ -36,12 +36,12 @@ public async Task<BrowserActionResult> ClickButton(BrowserActionParams actionPar
{
// Infer element if not found
var driverService = _services.GetRequiredService<WebDriverService>();
var html = await FilteredButtonHtml(actionParams.ConversationId);
var html = await FilteredButtonHtml(actionParams.ContextId);
var htmlElementContextOut = await driverService.InferElement(actionParams.Agent,
html,
actionParams.Context.ElementName,
actionParams.MessageId);
elements = Locator(actionParams.ConversationId, htmlElementContextOut);
elements = Locator(actionParams.ContextId, htmlElementContextOut);

if (elements == null)
{
Expand All @@ -54,7 +54,7 @@ public async Task<BrowserActionResult> ClickButton(BrowserActionParams actionPar
try
{
await elements.ClickAsync();
await _instance.Wait(actionParams.ConversationId);
await _instance.Wait(actionParams.ContextId);

result.IsSuccess = true;
}
Expand All @@ -67,12 +67,12 @@ public async Task<BrowserActionResult> ClickButton(BrowserActionParams actionPar
return result;
}

private async Task<string> FilteredButtonHtml(string conversationId)
private async Task<string> FilteredButtonHtml(string contextId)
{
var driverService = _services.GetRequiredService<WebDriverService>();

// Retrieve the page raw html and infer the element path
var body = await _instance.GetPage(conversationId).QuerySelectorAsync("body");
var body = await _instance.GetPage(contextId).QuerySelectorAsync("body");

var str = new List<string>();
/*var anchors = await body.QuerySelectorAllAsync("a");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ public partial class PlaywrightWebDriver
public async Task<BrowserActionResult> ClickElement(BrowserActionParams actionParams)
{
var result = new BrowserActionResult();
await _instance.Wait(actionParams.ConversationId);
await _instance.Wait(actionParams.ContextId);

var page = _instance.GetPage(actionParams.ConversationId);
var page = _instance.GetPage(actionParams.ContextId);
ILocator locator = default;
int count = 0;

Expand Down Expand Up @@ -51,7 +51,7 @@ public async Task<BrowserActionResult> ClickElement(BrowserActionParams actionPa
await locator.ClickAsync();

// Triggered ajax
await _instance.Wait(actionParams.ConversationId);
await _instance.Wait(actionParams.ContextId);

result.IsSuccess = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;

public partial class PlaywrightWebDriver
{
public async Task CloseBrowser(string conversationId)
public async Task CloseBrowser(string contextId)
{
await _instance.Close(conversationId);
await _instance.Close(contextId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;

public partial class PlaywrightWebDriver
{
public async Task CloseCurrentPage(string contextId)
{
await _instance.CloseCurrentPage(contextId);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
using BotSharp.Abstraction.Browsing.Enums;

namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;

public partial class PlaywrightWebDriver
{
public async Task DoAction(MessageInfo message, ElementActionArgs action, BrowserActionResult result)
{
var page = _instance.GetPage(message.ConversationId);
var page = _instance.GetPage(message.ContextId);
ILocator locator = page.Locator(result.Selector);

if (action.Action == BroswerActionEnum.Click)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;

public partial class PlaywrightWebDriver
{
public async Task<T> EvaluateScript<T>(string conversationId, string script)
public async Task<T> EvaluateScript<T>(string contextId, string script)
{
await _instance.Wait(conversationId);
await _instance.Wait(contextId);

return await _instance.GetPage(conversationId).EvaluateAsync<T>(script);
return await _instance.GetPage(contextId).EvaluateAsync<T>(script);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ public partial class PlaywrightWebDriver
{
public async Task<string> ExtractData(BrowserActionParams actionParams)
{
await _instance.Wait(actionParams.ConversationId);
await _instance.Wait(actionParams.ContextId);

await Task.Delay(3000);

// Retrieve the page raw html and infer the element path
var body = await _instance.GetPage(actionParams.ConversationId).QuerySelectorAsync("body");
var body = await _instance.GetPage(actionParams.ContextId).QuerySelectorAsync("body");
var content = await body.InnerTextAsync();

var driverService = _services.GetRequiredService<WebDriverService>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public partial class PlaywrightWebDriver
{
public async Task<string> GetAttributeValue(MessageInfo message, ElementLocatingArgs location, BrowserActionResult result)
{
var page = _instance.GetPage(message.ConversationId);
var page = _instance.GetPage(message.ContextId);
ILocator locator = page.Locator(result.Selector);
var value = string.Empty;

Expand Down
Loading