Commit 33d06d8e authored by Daniel Cheng's avatar Daniel Cheng Committed by Chromium LUCI CQ

Add test that frame tree cannot be corrupted by JS during Frame::Swap()

The new tests case mutates the frame tree in a JS unload event handler
that runs in the middle of Frame::Swap(), to ensure that Frame::Swap()
does not accidentally corrupt the frame tree.

Bug: 1139872
Change-Id: Id26039caeecaff57f1b32f9c1e312f98e2e3fb64
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2596539
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarFergal Daly <fergal@chromium.org>
Cr-Commit-Position: refs/heads/master@{#838777}
parent c5317dc1
...@@ -8940,6 +8940,34 @@ TEST_F(WebFrameTest, SwapMainFrameWhileLoading) { ...@@ -8940,6 +8940,34 @@ TEST_F(WebFrameTest, SwapMainFrameWhileLoading) {
&frame_client); &frame_client);
} }
TEST_F(WebFrameTest, SwapChildAddFrameInUnload) {
frame_test_helpers::WebViewHelper web_view_helper;
// This sets up a main frame with one child frame. When the document in the
// child frame is unloaded (e.g. due to the `Frame::Swap()` call below), the
// unload handler will insert a new <iframe> into the main frame's document.
RegisterMockedHttpURLLoad("add-frame-in-unload-main.html");
RegisterMockedHttpURLLoad("add-frame-in-unload-subframe.html");
web_view_helper.InitializeAndLoad(base_url_ +
"add-frame-in-unload-main.html");
WebLocalFrame* new_frame = web_view_helper.CreateProvisional(
*web_view_helper.LocalMainFrame()->FirstChild());
// This triggers the unload handler in the child frame's Document, mutating
// the frame tree during the `Frame::Swap()` call.
web_view_helper.LocalMainFrame()->FirstChild()->Swap(new_frame);
// TODO(dcheng): This is currently required to trigger a crash when the bug is
// not fixed. Removing a frame from the frame tree will fail one of the
// consistency checks in `Frame::RemoveChild()` if the frame tree is
// corrupted. This should be replaced with a test helper that comprehensively
// validates that a frame tree is not corrupted: this helper could also be
// used to simplify the various SwapAndVerify* helpers below.
web_view_helper.LocalMainFrame()->ExecuteScript(
WebScriptSource("document.querySelector('iframe').remove()"));
}
void WebFrameTest::SwapAndVerifyFirstChildConsistency(const char* const message, void WebFrameTest::SwapAndVerifyFirstChildConsistency(const char* const message,
WebFrame* parent, WebFrame* parent,
WebFrame* new_child) { WebFrame* new_child) {
......
<!DOCTYPE html>
<body><iframe src="add-frame-in-unload-subframe.html"></iframe></body>
<!DOCTYPE html>
<script>
window.addEventListener('unload', () => {
window.top.document.body.appendChild(document.createElement('iframe'));
});
</script>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment