Commit 1b0a991d authored by arthursonzogni's avatar arthursonzogni Committed by Commit Bot

Force error page to be classified as cross-document.

Bug https://crbug.com/1018385 is caused by navigation initially
classified as "same-document" committing error pages.

During the commit phase of the navigation, the NavigationRequest is
transfered in one of these RenderFrameHostImpl's bucket:
 - same_document_navigation_request_
 - navigation_requests_

A navigation classified as "same-document" ends up in the bucket
incompatible with error pages.
DidCommitPerNavigationMojoInterfaceNavigation expects to find the
navigation is the other bucket.

Add several regressions tests, including WPT tests.

Bug: 1018385
Change-Id: I3d92af1dd487f7b60a3e50a792716a07b074e5eb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1886339
Commit-Queue: Arthur Sonzogni <arthursonzogni@chromium.org>
Reviewed-by: default avatarNasko Oskov <nasko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#712541}
parent 9745d1e6
......@@ -613,6 +613,28 @@ network::mojom::IPAddressSpace CalculateIPAddressSpace(
return network::mojom::IPAddressSpace::kPublic;
}
// Convert the navigation type to the appropriate cross-document one.
//
// This is currently used when:
// 1) Restarting a same-document navigation as cross-document.
// 2) Committing an error page after blocking a same-document navigations.
mojom::NavigationType ConvertToCrossDocumentType(mojom::NavigationType type) {
switch (type) {
case mojom::NavigationType::SAME_DOCUMENT:
return mojom::NavigationType::DIFFERENT_DOCUMENT;
case mojom::NavigationType::HISTORY_SAME_DOCUMENT:
return mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT;
case mojom::NavigationType::RELOAD:
case mojom::NavigationType::RELOAD_BYPASSING_CACHE:
case mojom::NavigationType::RELOAD_ORIGINAL_REQUEST_URL:
case mojom::NavigationType::RESTORE:
case mojom::NavigationType::RESTORE_WITH_POST:
case mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT:
case mojom::NavigationType::DIFFERENT_DOCUMENT:
return type;
}
}
} // namespace
// static
......@@ -1335,15 +1357,8 @@ void NavigationRequest::ResetForCrossDocumentRestart() {
render_frame_host_ = nullptr;
// Convert the navigation type to the appropriate cross-document one.
if (common_params_->navigation_type ==
mojom::NavigationType::HISTORY_SAME_DOCUMENT) {
common_params_->navigation_type =
mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT;
} else {
DCHECK(common_params_->navigation_type ==
mojom::NavigationType::SAME_DOCUMENT);
common_params_->navigation_type = mojom::NavigationType::DIFFERENT_DOCUMENT;
}
common_params_->navigation_type =
ConvertToCrossDocumentType(common_params_->navigation_type);
}
void NavigationRequest::RegisterSubresourceOverride(
......@@ -2360,6 +2375,14 @@ void NavigationRequest::OnWillProcessResponseChecksComplete(
void NavigationRequest::CommitErrorPage(
const base::Optional<std::string>& error_page_content) {
UpdateCommitNavigationParamsHistory();
// Error pages are always cross-document.
//
// This is useful when a same-document navigation is blocked and commit an
// error page instead. See https://crbug.com/1018385.
common_params_->navigation_type =
ConvertToCrossDocumentType(common_params_->navigation_type);
frame_tree_node_->TransferNavigationRequestOwnership(render_frame_host_);
// Error pages commit in an opaque origin in the renderer process. If this
// NavigationRequest resulted in committing an error page, set
......
......@@ -3174,4 +3174,25 @@ IN_PROC_BROWSER_TEST_P(NavigationUrlRewriteBrowserTest, RewriteToNoAccess) {
}
}
// Update the fragment part of the URL while it is currently displaying an error
// page. Regression test https://crbug.com/1018385
IN_PROC_BROWSER_TEST_P(NavigationBrowserTest,
SameDocumentNavigationInErrorPage) {
WebContents* wc = shell()->web_contents();
NavigationHandleCommitObserver navigation_0(wc, GURL("about:srcdoc#0"));
NavigationHandleCommitObserver navigation_1(wc, GURL("about:srcdoc#1"));
// Big warning: about:srcdoc is not supposed to be valid browser-initiated
// main-frame navigation, it is currently blocked by the NavigationRequest.
// It is used here to reproduce bug https://crbug.com/1018385. Please avoid
// copying this kind of navigation in your own tests.
EXPECT_FALSE(NavigateToURL(shell(), GURL("about:srcdoc#0")));
EXPECT_FALSE(NavigateToURL(shell(), GURL("about:srcdoc#1")));
EXPECT_TRUE(navigation_0.has_committed());
EXPECT_TRUE(navigation_1.has_committed());
EXPECT_FALSE(navigation_0.was_same_document());
EXPECT_FALSE(navigation_1.was_same_document());
}
} // namespace content
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<html>
<body></body>
<script>
async_test(async test => {
// 1. Load an iframe (not blocked).
let iframe = document.createElement("iframe");
{
iframe.name = "theiframe";
iframe.src =
"http://www1.{{host}}/content-security-policy/support/frame.html#0";
let iframeLoaded = new Promise(resolve => { iframe.onload = resolve; });
document.body.appendChild(iframe);
await iframeLoaded;
}
// 2. Start blocking iframes using CSP frame-src 'none'.
{
let meta = document.createElement('meta');
meta.httpEquiv = "Content-Security-Policy";
meta.content = "frame-src 'none'";
document.getElementsByTagName('head')[0].appendChild(meta);
}
// 3. Blocked same-document navigation using iframe.src.
{
let violation = new Promise(resolve => {
window.addEventListener('securitypolicyviolation', resolve);
});
iframe.src =
"http://www1.{{host}}/content-security-policy/support/frame.html#1";
await violation;
}
// 4. Blocked same-document navigation using window.open.
{
let violation = new Promise(resolve => {
window.addEventListener('securitypolicyviolation', resolve);
});
window.open(
"http://www1.{{host}}/content-security-policy/support/frame.html#2",
"theiframe");
await violation;
}
// 5. Regression test for https://crbug.com/1018385. The browser should
// not crash while displaying the error page.
await new Promise(resolve => window.setTimeout(resolve, 1000));
test.done();
}, "Same-document navigations in an iframe blocked by CSP frame-src dynamically using the <meta> tag");
</script>
</html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<html>
<body></body>
<script>
let crossOriginUrl =
"http://www1.{{host}}/content-security-policy/support/frame.html";
async_test(async test => {
test.done();
let iframe = document.createElement("iframe");
document.body.appendChild(iframe);
for(let hash of ["#0", "#1"]) {
let violation = new Promise(resolve => {
window.addEventListener('securitypolicyviolation', resolve);
});
iframe.src = crossOriginUrl + hash;
await violation;
}
test.done();
}, "Same-document navigation in an iframe blocked by CSP frame-src");
</script>
</html>
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