Skip to content

Commit 7fa4d5f

Browse files
authored
Merge pull request #1218 from TheJayMann/issue-1205-iframe-targets-2
Add support for finding targets in auxilary browsing contexts
2 parents 6e196f0 + e89ab5c commit 7fa4d5f

File tree

2 files changed

+100
-1
lines changed

2 files changed

+100
-1
lines changed

src/AngleSharp.Core.Tests/Html/IframeTargets.cs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ public async Task AnchorTargetsSiblingIframeInIframe()
263263
}
264264

265265
[Test]
266-
public async Task AnchorTargetsIframeInDifferentWindow()
266+
public async Task AnchorTargetsIframeFromDifferentWindow()
267267
{
268268
var context = BrowsingContext.New(Configuration.Default.WithVirtualRequester(req => req.Address.Href switch
269269
{
@@ -327,6 +327,71 @@ public async Task AnchorTargetsIframeInDifferentWindow()
327327
Assert.AreEqual("iframe content", headerTexts[0].InnerHtml);
328328
}
329329

330+
[Test]
331+
public async Task AnchorTargetsIframeInDifferentWindow()
332+
{
333+
var context = BrowsingContext.New(Configuration.Default.WithVirtualRequester(req => req.Address.Href switch
334+
{
335+
"https://localhost/inner-iframe.html" => CreateResponse(req.Address,
336+
// language=html
337+
"""
338+
<html>
339+
<body>
340+
<h1>iframe content</h1>
341+
</body>
342+
</html>
343+
"""u8
344+
),
345+
"https://localhost/new-window.html" => CreateResponse(req.Address,
346+
// language=html
347+
"""
348+
<html>
349+
<body>
350+
<iframe id="iframe" name="iframe"></iframe>
351+
</body>
352+
</html>
353+
"""u8
354+
),
355+
"https://localhost/" => CreateResponse(req.Address,
356+
// language=html
357+
"""
358+
<html>
359+
<body>
360+
<a href="inner-iframe.html" id="frame-link" target="iframe">Load frame</a>
361+
<a href="new-window.html" id="window-link" target="new-window">Load window</a>
362+
</body>
363+
</html>
364+
"""u8
365+
),
366+
_ => CreateNotFoundResponse(req.Address),
367+
}));
368+
369+
var doc = await context.OpenAsync("https://localhost/");
370+
371+
var newWindowLink = doc.GetElementById("window-link") as IHtmlAnchorElement;
372+
Assert.IsNotNull(newWindowLink);
373+
newWindowLink.DoClick();
374+
375+
await Task.Delay(1000);
376+
377+
var newWindowDoc = context.FindChild("new-window")?.Active;
378+
Assert.IsNotNull(newWindowDoc);
379+
380+
var frameLink = doc.GetElementById("frame-link") as IHtmlAnchorElement;
381+
Assert.IsNotNull(frameLink);
382+
frameLink.DoClick();
383+
384+
await Task.Delay(1000);
385+
386+
var iframe = newWindowDoc.GetElementById("iframe") as IHtmlInlineFrameElement;
387+
Assert.IsNotNull(iframe?.ContentDocument);
388+
389+
var headerTexts = iframe.ContentDocument.GetElementsByTagName("h1");
390+
Assert.IsNotNull(headerTexts);
391+
Assert.AreEqual(1, headerTexts.Length);
392+
Assert.AreEqual("iframe content", headerTexts[0].InnerHtml);
393+
}
394+
330395
[Test]
331396
public async Task AnchorTargetsCurrentWindowWithTop()
332397
{

src/AngleSharp/BrowsingContext.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public sealed class BrowsingContext : EventTarget, IBrowsingContext, IDisposable
2121
private readonly Boolean _isFrameContext;
2222
private readonly IHistory? _history;
2323
private readonly Dictionary<String, WeakReference<IBrowsingContext>> _children;
24+
private readonly List<WeakReference<IBrowsingContext>> _contextGroup;
2425

2526
#endregion
2627

@@ -45,6 +46,7 @@ private BrowsingContext(Sandboxes security)
4546
_originalServices = _services;
4647
_security = security;
4748
_children = [];
49+
_contextGroup = [];
4850
}
4951

5052
internal BrowsingContext(IEnumerable<Object> services, Sandboxes security)
@@ -207,6 +209,19 @@ internal IBrowsingContext CreateChild(String? name, Sandboxes security, Boolean
207209
{
208210
var context = new BrowsingContext(this, security, isFrameContext);
209211

212+
// if the new context is not a frame context, then it should be added
213+
// to the top-most browsing context, as a new top-level auxilary
214+
// browser context
215+
if (!isFrameContext)
216+
{
217+
if (_contextGroup is null)
218+
{
219+
// _parent should not be null if _contextGroup is null
220+
return _parent!.CreateChild(name, security);
221+
}
222+
_contextGroup.Add(new(context));
223+
}
224+
210225
if (name is { Length: > 0 })
211226
{
212227
_children[name] = new WeakReference<IBrowsingContext>(context);
@@ -230,7 +245,26 @@ internal IBrowsingContext CreateChild(String? name, Sandboxes security, Boolean
230245
foundChildContext = currentContext.FindChildRecursive(name, excludedChild);
231246
excludedChild = currentContext;
232247
currentContext = currentContext.Parent as BrowsingContext;
248+
}
233249

250+
if (foundChildContext is null && excludedChild is BrowsingContext { _contextGroup : not null and var group })
251+
{
252+
// TODO
253+
// if the initial browsing context was part of a top-level auxilary browsing context,
254+
// it should be filtered out so that it is not searched again
255+
foreach (var contextRef in group)
256+
{
257+
if (!contextRef.TryGetTarget(out var c) || c is not BrowsingContext context)
258+
{
259+
continue;
260+
}
261+
262+
foundChildContext = context.FindChildRecursive(name, null);
263+
264+
if (foundChildContext is not null) {
265+
return foundChildContext;
266+
}
267+
}
234268
}
235269

236270
return foundChildContext;

0 commit comments

Comments
 (0)