Skip to content

Commit

Permalink
Anchor navigation support in bidi
Browse files Browse the repository at this point in the history
  • Loading branch information
kblok committed Nov 6, 2024
1 parent 42e30df commit 1ecb6ce
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -120,21 +120,6 @@
"FAIL"
]
},
{
"comment": "This is part of organizing the webdriver bidi implementation, We will remove it one by one",
"testIdPattern": "[navigation.spec] *should work with anchor navigation*",
"platforms": [
"darwin",
"linux",
"win32"
],
"parameters": [
"webDriverBiDi"
],
"expectations": [
"FAIL"
]
},
{
"comment": "This is part of organizing the webdriver bidi implementation, We will remove it one by one",
"testIdPattern": "[navigation.spec] * should fail when main resources failed to load",
Expand Down
19 changes: 16 additions & 3 deletions lib/PuppeteerSharp/Bidi/BidiFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,22 @@ async Task<Navigation> WaitForEventNavigationAsync()

var waitForLoadTask = WaitForLoadAsync(options);

Task<bool> waitForFragmentTask;

if (navigationTcs.Task.Result.FragmentReceived)
{
waitForFragmentTask = Task.FromResult(true);
}
else
{
var waitForFragmentTcs = new TaskCompletionSource<bool>();
navigationTcs.Task.Result.Fragment += (sender, args) => waitForFragmentTcs.TrySetResult(true);
waitForFragmentTask = waitForFragmentTcs.Task;
}

// TODO: Add frame detached event.
// TODO: Add fragment, failed and aborted events.
await Task.WhenAny(waitForLoadTask).WithTimeout(timeout).ConfigureAwait(false);
// TODO: Add failed and aborted events.
await Task.WhenAny(waitForLoadTask, waitForFragmentTask).WithTimeout(timeout).ConfigureAwait(false);

return navigationTcs.Task.Result;
}
Expand Down Expand Up @@ -168,7 +181,7 @@ internal static BidiFrame From(BidiPage parentPage, BidiFrame parentFrame, Brows
private PuppeteerException RewriteNavigationError(Exception ex, string url, int timeoutSettingsNavigationTimeout)
{
return ex is TimeoutException
? new NavigationException($"Navigation timeout of {timeoutSettingsNavigationTimeout} ms exceeded", url)
? new NavigationException($"Navigation timeout of {timeoutSettingsNavigationTimeout} ms exceeded", url, ex)
: new PuppeteerException("Navigation failed: " + ex.Message, ex);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/PuppeteerSharp/Bidi/Core/BrowsingContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ private void Initialize()
OnLoad();
};

Session.BrowsingcontextNavigationStarted += (sender, args) =>
Session.BrowsingContextNavigationStarted += (sender, args) =>
{
if (args.BrowsingContextId != Id)
{
Expand Down
21 changes: 15 additions & 6 deletions lib/PuppeteerSharp/Bidi/Core/Navigation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ internal class Navigation
{
private readonly BrowsingContext _browsingContext;
private Navigation _navigation;
private string _id;

private Navigation(BrowsingContext browsingContext)
{
Expand All @@ -44,12 +43,18 @@ private Navigation(BrowsingContext browsingContext)

public event EventHandler<RequestEventArgs> RequestCreated;

public string Id { get; private set; }

public Request Request { get; private set; }

public Session Session => _browsingContext.UserContext.Browser.Session;

public bool IsDisposed { get; private set; }

// We have some race conditions puppeteer doesn't have.
// We might receive a fragment before the BidiFrame sets up the listener.
public bool FragmentReceived { get; set; }

public static Navigation From(BrowsingContext context)
{
var navigation = new Navigation(context);
Expand Down Expand Up @@ -83,7 +88,7 @@ private void Initialize()
Request.Redirect += (sender, args) => Request = args.Request;
};

Session.BrowsingcontextNavigationStarted += (sender, args) =>
Session.BrowsingContextNavigationStarted += (sender, args) =>
{
if (args.BrowsingContextId != _browsingContext.Id || _navigation != null)
{
Expand Down Expand Up @@ -112,7 +117,11 @@ private void HandleNavigation(WebDriverBiDi.BrowsingContext.NavigationEventArgs
Dispose();
}

private void OnFragment(NavigationEventArgs args) => Fragment?.Invoke(this, args);
private void OnFragment(NavigationEventArgs args)
{
FragmentReceived = true;
Fragment?.Invoke(this, args);
}

private void OnAborted(NavigationEventArgs args) => Aborted?.Invoke(this, args);

Expand All @@ -135,12 +144,12 @@ private bool Matches(string navigation)
return false;
}

if (_id == null)
if (Id == null)
{
_id = navigation;
Id = navigation;
return true;
}

return _id == navigation;
return Id == navigation;
}
}
21 changes: 18 additions & 3 deletions lib/PuppeteerSharp/Bidi/Core/Session.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using PuppeteerSharp.Helpers;
using WebDriverBiDi;
using WebDriverBiDi.BrowsingContext;
using WebDriverBiDi.Network;
Expand All @@ -33,13 +34,15 @@ namespace PuppeteerSharp.Bidi.Core;

internal class Session(BiDiDriver driver, NewCommandResult info) : IDisposable
{
private readonly ConcurrentSet<WebDriverBiDi.BrowsingContext.NavigationEventArgs> _fragmentSeen = new();

public event EventHandler<SessionEndArgs> Ended;

public event EventHandler<BrowsingContextEventArgs> BrowsingContextContextCreated;

public event EventHandler<BrowsingContextEventArgs> BrowsingContextContextDestroyed;

public event EventHandler<WebDriverBiDi.BrowsingContext.NavigationEventArgs> BrowsingcontextNavigationStarted;
public event EventHandler<WebDriverBiDi.BrowsingContext.NavigationEventArgs> BrowsingContextNavigationStarted;

public event EventHandler<WebDriverBiDi.BrowsingContext.NavigationEventArgs> BrowsingContextLoad;

Expand Down Expand Up @@ -97,7 +100,7 @@ private async Task InitializeAsync()
Driver.BrowsingContext.OnDomContentLoaded.AddObserver(OnBrowsingContextDomContentLoaded);
Driver.BrowsingContext.OnLoad.AddObserver(OnBrowsingContextLoad);
Driver.BrowsingContext.OnNavigationStarted.AddObserver(OnBrowsingContextNavigationStarted);
Driver.BrowsingContext.OnFragmentNavigated.AddObserver(OnBrowsingContextFragmentNavigated);
Driver.BrowsingContext.OnFragmentNavigated.AddObserver(OnFragmentNavigated);
Driver.BrowsingContext.OnNavigationFailed.AddObserver(OnBrowsingContextNavigationFailed);
Driver.BrowsingContext.OnNavigationAborted.AddObserver(OnBrowsingContextNavigationAborted);
Driver.Network.OnBeforeRequestSent.AddObserver(OnBeforeRequestSent);
Expand All @@ -106,6 +109,18 @@ private async Task InitializeAsync()
Driver.Network.OnResponseCompleted.AddObserver(OnNetworkResponseCompleted);
}

private void OnFragmentNavigated(WebDriverBiDi.BrowsingContext.NavigationEventArgs info)
{
if (_fragmentSeen.Contains(info))
{
return;
}

_fragmentSeen.Add(info);
OnBrowsingContextNavigationStarted(info);
OnBrowsingContextFragmentNavigated(info);
}

private void OnNetworkResponseCompleted(ResponseCompletedEventArgs obj) => NetworkResponseComplete?.Invoke(this, obj);

private void OnNetworkFetchError(FetchErrorEventArgs obj) => NetworkFetchError?.Invoke(this, obj);
Expand All @@ -120,7 +135,7 @@ private async Task InitializeAsync()

private void OnBrowsingContextFragmentNavigated(WebDriverBiDi.BrowsingContext.NavigationEventArgs obj) => BrowsingContextFragmentNavigated?.Invoke(this, obj);

private void OnBrowsingContextNavigationStarted(WebDriverBiDi.BrowsingContext.NavigationEventArgs obj) => BrowsingcontextNavigationStarted?.Invoke(this, obj);
private void OnBrowsingContextNavigationStarted(WebDriverBiDi.BrowsingContext.NavigationEventArgs obj) => BrowsingContextNavigationStarted?.Invoke(this, obj);

private void OnBrowsingContextLoad(WebDriverBiDi.BrowsingContext.NavigationEventArgs arg) => BrowsingContextLoad?.Invoke(this, arg);

Expand Down
3 changes: 2 additions & 1 deletion lib/PuppeteerSharp/NavigationException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ public NavigationException(string message) : base(message)
/// </summary>
/// <param name="message">Message.</param>
/// <param name="url">Url.</param>
public NavigationException(string message, string url) : base(message)
/// <param name="innerException">Inner exception.</param>
public NavigationException(string message, string url, Exception innerException = null) : base(message, innerException)
{
Url = url;
}
Expand Down

0 comments on commit 1ecb6ce

Please sign in to comment.