Skip to content
This repository was archived by the owner on Jan 30, 2025. It is now read-only.

Commit 9884e91

Browse files
authored
Merge pull request #677 from grafana/fix/669-iframe-panic
Fix: panic on navigating on remote iframes
2 parents 3cee653 + 83b795a commit 9884e91

File tree

5 files changed

+70
-8
lines changed

5 files changed

+70
-8
lines changed

.github/workflows/test.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ jobs:
4343
args[1]="1"
4444
export GOMAXPROCS=1
4545
fi
46+
export XK6_HEADLESS=true
4647
go test "${args[@]}" -timeout 5m ./...
4748
4849
test-tip:
@@ -71,6 +72,7 @@ jobs:
7172
go version
7273
export GOMAXPROCS=2
7374
args=("-p" "2" "-race")
75+
export XK6_HEADLESS=true
7476
go test "${args[@]}" -timeout 5m ./...
7577
7678
test-current-cov:
@@ -99,6 +101,7 @@ jobs:
99101
args[1]="1"
100102
export GOMAXPROCS=1
101103
fi
104+
export XK6_HEADLESS=true
102105
echo "mode: set" > coverage.txt
103106
for pkg in $(go list ./... | grep -v vendor); do
104107
list=$(go list -test -f '{{ join .Deps "\n"}}' $pkg | grep github.com/grafana/xk6-browser | grep -v vendor || true)

common/frame_manager.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515

1616
"github.com/chromedp/cdproto/cdp"
1717
"github.com/chromedp/cdproto/network"
18+
cdppage "github.com/chromedp/cdproto/page"
1819
)
1920

2021
// FrameManager manages all frames in a page and their life-cycles, it's a purely internal component.
@@ -166,20 +167,26 @@ func (m *FrameManager) frameAttached(frameID cdp.FrameID, parentFrameID cdp.Fram
166167
}
167168
}
168169

169-
func (m *FrameManager) frameDetached(frameID cdp.FrameID) {
170+
func (m *FrameManager) frameDetached(frameID cdp.FrameID, reason cdppage.FrameDetachedReason) {
170171
m.logger.Debugf("FrameManager:frameDetached", "fmid:%d fid:%v", m.ID(), frameID)
171172

172-
// TODO: use getFrameByID here
173-
m.framesMu.RLock()
174-
frame, ok := m.frames[frameID]
175-
m.framesMu.RUnlock()
176-
if !ok {
173+
frame := m.getFrameByID(frameID)
174+
if frame == nil {
177175
m.logger.Debugf("FrameManager:frameDetached:return",
178176
"fmid:%d fid:%v cannot find frame",
179177
m.ID(), frameID)
180178
return
181179
}
182-
// TODO: possible data race? the frame may have gone.
180+
181+
if reason == cdppage.FrameDetachedReasonSwap {
182+
// When a local frame is swapped out for a remote
183+
// frame, we want to keep the current frame which is
184+
// still referenced by the (incoming) remote frame, but
185+
// remove all its child frames.
186+
m.removeChildFramesRecursively(frame)
187+
return
188+
}
189+
183190
m.removeFramesRecursively(frame)
184191
}
185192

common/frame_session.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ func (fs *FrameSession) onFrameDetached(frameID cdp.FrameID, reason cdppage.Fram
639639
"sid:%v tid:%v fid:%v reason:%s",
640640
fs.session.ID(), fs.targetID, frameID, reason)
641641

642-
fs.manager.frameDetached(frameID)
642+
fs.manager.frameDetached(frameID, reason)
643643
}
644644

645645
func (fs *FrameSession) onFrameNavigated(frame *cdp.Frame, initial bool) {

tests/frame_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package tests
22

33
import (
4+
"os"
5+
"strconv"
46
"testing"
57

68
"github.com/dop251/goja"
@@ -72,3 +74,46 @@ func TestFrameDismissDialogBox(t *testing.T) {
7274
})
7375
}
7476
}
77+
78+
func TestFrameNoPanicWithEmbeddedIFrame(t *testing.T) {
79+
if strValue, ok := os.LookupEnv("XK6_HEADLESS"); ok {
80+
if value, err := strconv.ParseBool(strValue); err == nil && value {
81+
// We're skipping this when running in headless
82+
// environments since the bug that the test fixes
83+
// only surfaces when in headfull mode.
84+
// Remove this skip once we have headfull mode in
85+
// CI: https://github.com/grafana/xk6-browser/issues/678
86+
t.Skip("skipped when in headless mode")
87+
}
88+
}
89+
90+
t.Parallel()
91+
92+
opts := defaultLaunchOpts()
93+
opts.Headless = false
94+
b := newTestBrowser(t, withFileServer(), opts)
95+
p := b.NewPage(nil)
96+
97+
var result string
98+
err := b.await(func() error {
99+
opts := b.toGojaValue(struct {
100+
WaitUntil string `js:"waitUntil"`
101+
}{
102+
WaitUntil: "load",
103+
})
104+
pageGoto := p.Goto(
105+
b.staticURL("embedded_iframe.html"),
106+
opts,
107+
)
108+
109+
b.promise(pageGoto).
110+
then(func() {
111+
result = p.TextContent("#doneDiv", nil)
112+
})
113+
114+
return nil
115+
})
116+
require.NoError(t, err)
117+
118+
assert.EqualValues(t, "Done!", result)
119+
}

tests/static/embedded_iframe.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<html>
2+
<head></head>
3+
<body>
4+
<div id='doneDiv'></div>
5+
<iframe src='https://www.youtube.com/embed/gwO7k5RTE54?wmode=opaque&amp;enablejsapi=1' onload='document.getElementById("doneDiv").innerText = "Done!"'></iframe>
6+
</body>
7+
</html>

0 commit comments

Comments
 (0)