Skip to content

Commit

Permalink
Merge pull request #2314 from hardkoded/page-target-class
Browse files Browse the repository at this point in the history
Introduce an internal PageTarget subclass
  • Loading branch information
kblok authored Sep 13, 2023
2 parents 962993c + 8d53b11 commit d6a2106
Show file tree
Hide file tree
Showing 8 changed files with 250 additions and 206 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ public async Task ShouldWaitForTarget()

[PuppeteerTest("browsercontext.spec.ts", "BrowserContext", "should timeout waiting for a non-existent target")]
[PuppeteerTimeout]
public async Task ShouldTimeoutWaitingForNonExistantTarget()
public async Task ShouldTimeoutWaitingForNonExistentTarget()
{
var context = await Browser.CreateIncognitoBrowserContextAsync();
Assert.ThrowsAsync<TimeoutException>(()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace PuppeteerSharp.Tests.DefaultBrowserContextTests
{
public class BrowserTargetEventsTests : PuppeteerBrowserBaseTest
public class BrowserTargetEventsTests : PuppeteerBaseTest
{
public BrowserTargetEventsTests(): base()
{
Expand All @@ -19,13 +19,16 @@ public BrowserTargetEventsTests(): base()
[Skip(SkipAttribute.Targets.Firefox)]
public async Task ShouldWork()
{
using var browser = await Puppeteer.LaunchAsync(TestConstants.DefaultBrowserOptions());

var events = new List<string>();
Browser.TargetCreated += (_, _) => events.Add("CREATED");
Browser.TargetChanged += (_, _) => events.Add("CHANGED");
Browser.TargetDestroyed += (_, _) => events.Add("DESTROYED");
var page = await Browser.NewPageAsync();
browser.TargetCreated += (_, _) => events.Add("CREATED");
browser.TargetChanged += (_, _) => events.Add("CHANGED");
browser.TargetDestroyed += (_, _) => events.Add("DESTROYED");
var page = await browser.NewPageAsync();
await page.GoToAsync(TestConstants.EmptyPage);
await page.CloseAsync();

Assert.AreEqual(new[] { "CREATED", "CHANGED", "DESTROYED" }, events);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ public BrowserTargetEventsTests(): base()
[Skip(SkipAttribute.Targets.Firefox)]
public async Task ShouldWork()
{
using var browser = await Puppeteer.LaunchAsync(TestConstants.DefaultBrowserOptions());
var events = new List<string>();

Browser.TargetCreated += (_, _) => events.Add("CREATED");
Browser.TargetChanged += (_, _) => events.Add("CHANGED");
Browser.TargetDestroyed += (_, _) => events.Add("DESTROYED");
Expand Down
24 changes: 17 additions & 7 deletions lib/PuppeteerSharp/Browser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ public class Browser : IBrowser
private readonly ConcurrentDictionary<string, BrowserContext> _contexts;
private readonly ILogger<Browser> _logger;
private readonly Func<TargetInfo, bool> _targetFilterCallback;
private readonly Func<TargetInfo, bool> _isPageTargetFunc;
private readonly BrowserContext _defaultContext;
private readonly CustomQueriesManager _customQueriesManager = new();
private Task _closeTask;
Expand All @@ -43,7 +42,7 @@ internal Browser(
Connection = connection;
_targetFilterCallback = targetFilter ?? ((TargetInfo _) => true);
_logger = Connection.LoggerFactory.CreateLogger<Browser>();
_isPageTargetFunc =
IsPageTargetFunc =
isPageTargetFunc ??
new Func<TargetInfo, bool>((TargetInfo target) =>
{
Expand Down Expand Up @@ -140,6 +139,8 @@ public bool IsClosed

internal ITargetManager TargetManager { get; }

internal Func<TargetInfo, bool> IsPageTargetFunc { get; set; }

/// <inheritdoc/>
public Task<IPage> NewPageAsync() => _defaultContext.NewPageAsync();

Expand Down Expand Up @@ -478,16 +479,25 @@ private Target CreateTarget(TargetInfo targetInfo, CDPSession session)
context = _defaultContext;
}

if (IsPageTargetFunc(targetInfo))
{
return new PageTarget(
targetInfo,
session,
context,
TargetManager,
(bool isAutoAttachEmulated) => Connection.CreateSessionAsync(targetInfo, isAutoAttachEmulated),
IgnoreHTTPSErrors,
DefaultViewport,
ScreenshotTaskQueue);
}

return new Target(
targetInfo,
session,
context,
TargetManager,
(bool isAutoAttachEmulated) => Connection.CreateSessionAsync(targetInfo, isAutoAttachEmulated),
IgnoreHTTPSErrors,
DefaultViewport,
ScreenshotTaskQueue,
_isPageTargetFunc);
(bool isAutoAttachEmulated) => Connection.CreateSessionAsync(targetInfo, isAutoAttachEmulated));
}
}
}
6 changes: 5 additions & 1 deletion lib/PuppeteerSharp/BrowserContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ public Task<ITarget> WaitForTargetAsync(Func<ITarget, bool> predicate, WaitForOp
/// <inheritdoc/>
public async Task<IPage[]> PagesAsync()
=> (await Task.WhenAll(
Targets().Where(t => t.Type == TargetType.Page).Select(t => t.PageAsync())).ConfigureAwait(false))
Targets()
.Where(t =>
t.Type == TargetType.Page ||
(t.Type == TargetType.Other && Browser.IsPageTargetFunc((t as Target).TargetInfo)))
.Select(t => t.PageAsync())).ConfigureAwait(false))
.Where(p => p != null).ToArray();

/// <inheritdoc/>
Expand Down
2 changes: 1 addition & 1 deletion lib/PuppeteerSharp/ITarget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public interface ITarget
Task<ICDPSession> CreateCDPSessionAsync();

/// <summary>
/// Returns the <see cref="IPage"/> associated with the target. If the target is not <c>"page"</c> or <c>"background_page"</c> returns <c>null</c>.
/// Returns the <see cref="IPage"/> associated with the target. If the target is not <c>"page"</c>, <c>"webview"</c> or <c>"background_page"</c> returns <c>null</c>.
/// </summary>
/// <returns>a task that returns a <see cref="IPage"/>.</returns>
Task<IPage> PageAsync();
Expand Down
88 changes: 88 additions & 0 deletions lib/PuppeteerSharp/PageTarget.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using System;
using System.Threading.Tasks;
using PuppeteerSharp.Helpers;

namespace PuppeteerSharp
{
internal class PageTarget : Target
{
private readonly bool _ignoreHTTPSErrors;
private readonly ViewPortOptions _defaultViewport;
private readonly TaskQueue _screenshotTaskQueue;

public PageTarget(TargetInfo targetInfo, CDPSession session, BrowserContext context, ITargetManager targetManager, Func<bool, Task<CDPSession>> sessionFactory, bool ignoreHTTPSErrors, ViewPortOptions defaultViewport, TaskQueue screenshotTaskQueue)
: base(targetInfo, session, context, targetManager, sessionFactory)
{
_ignoreHTTPSErrors = ignoreHTTPSErrors;
_defaultViewport = defaultViewport;
_screenshotTaskQueue = screenshotTaskQueue;
PageTask = null;
}

internal Task<Page> PageTask { get; set; }

/// <inheritdoc/>
public override async Task<IPage> PageAsync()
{
if (PageTask == null)
{
var session = Session ?? await SessionFactory(true).ConfigureAwait(false);

PageTask = Page.CreateAsync(
session,
this,
_ignoreHTTPSErrors,
_defaultViewport,
_screenshotTaskQueue);
}

return await PageTask.ConfigureAwait(false);
}

protected override void Initialize()
{
_ = InitializedTaskWrapper.Task.ContinueWith(
async initializedTask =>
{
var success = initializedTask.Result;
if (!success)
{
return;
}
var opener = Opener as PageTarget;
var openerPageTask = opener?.PageTask;
if (openerPageTask == null || Type != TargetType.Page)
{
return;
}
var openerPage = (Page)await openerPageTask.ConfigureAwait(false);
if (!openerPage.HasPopupEventListeners)
{
return;
}
var popupPage = await PageAsync().ConfigureAwait(false);
openerPage.OnPopup(popupPage);
},
TaskScheduler.Default);
CheckIfInitialized();
}

protected override void CheckIfInitialized()
{
if (IsInitialized)
{
return;
}

IsInitialized = !string.IsNullOrEmpty(TargetInfo.Url);
if (IsInitialized)
{
InitializedTaskWrapper.TrySetResult(true);
}
}
}
}
Loading

0 comments on commit d6a2106

Please sign in to comment.