Commit 32ba6d46 authored by Nate Chapin's avatar Nate Chapin Committed by Commit Bot

Make cross origin fragment navigation timing attack defenses testable via internals API

This removes the need for dumpFrameLoadCallbacks(), which is difficult to make
consistent with and without site isolation

Bug: 619662
Change-Id: I94a553707c306eae4a755a2b2d3ddf45fa145bf7
Reviewed-on: https://chromium-review.googlesource.com/c/1354574Reviewed-by: default avatarMike West <mkwst@chromium.org>
Commit-Queue: Nate Chapin <japhet@chromium.org>
Cr-Commit-Position: refs/heads/master@{#613184}
parent 0400dfb6
......@@ -471,6 +471,15 @@ int Internals::getResourcePriority(const String& url, Document* document) {
return static_cast<int>(resource->GetResourceRequest().Priority());
}
bool Internals::doesWindowHaveUrlFragment(DOMWindow* window) {
if (window->IsRemoteDOMWindow())
return false;
return ToLocalFrame(window->GetFrame())
->GetDocument()
->Url()
.HasFragmentIdentifier();
}
String Internals::getResourceHeader(const String& url,
const String& header,
Document* document) {
......
......@@ -108,6 +108,8 @@ class Internals final : public ScriptWrappable {
int getResourcePriority(const String& url, Document*);
String getResourceHeader(const String& url, const String& header, Document*);
bool doesWindowHaveUrlFragment(DOMWindow*);
CSSStyleDeclaration* computedStyleIncludingVisitedInfo(Node*) const;
void setBrowserControlsState(float top_height,
......
......@@ -44,6 +44,8 @@ enum EffectiveConnectionType {
unsigned long getResourcePriority (DOMString url, Document document);
DOMString getResourceHeader (DOMString url, DOMString header, Document document);
bool doesWindowHaveUrlFragment(Window window);
CSSStyleDeclaration computedStyleIncludingVisitedInfo(Node node);
ShadowRoot createUserAgentShadowRoot(Element host);
......
......@@ -147,10 +147,6 @@ crbug.com/771003 virtual/outofblink-cors/http/tests/security/mixedContent/insecu
crbug.com/393285 http/tests/text-autosizing/narrow-iframe.html [ Failure Crash ]
crbug.com/393285 http/tests/text-autosizing/wide-iframe.html [ Failure Crash ]
# Console message differences (e.g. full URI vs origin-only):
crbug.com/619662 http/tests/navigation/cross-origin-fragment-navigation-is-async.html [ Failure ]
crbug.com/619662 virtual/outofblink-cors-ns/http/tests/navigation/cross-origin-fragment-navigation-is-async.html [ Failure ]
crbug.com/619662 virtual/outofblink-cors/http/tests/navigation/cross-origin-fragment-navigation-is-async.html [ Failure ]
crbug.com/619662 virtual/stable/http/tests/navigation/cross-origin-fragment-navigation-is-async.html [ Failure ]
crbug.com/669083 http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture.html [ Failure ]
crbug.com/669083 virtual/outofblink-cors-ns/http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture.html [ Failure ]
crbug.com/669083 virtual/outofblink-cors/http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture.html [ Failure ]
......
frame "<!--framePath //<!--frame0-->-->" - didReceiveTitle:
frame "<!--framePath //<!--frame0-->-->" - didStartProvisionalLoadForFrame
main frame - didReceiveTitle:
main frame - didFinishDocumentLoadForFrame
frame "<!--framePath //<!--frame0-->-->" - didCommitLoadForFrame
frame "<!--framePath //<!--frame0-->-->" - didReceiveTitle:
frame "<!--framePath //<!--frame0-->-->" - didFinishDocumentLoadForFrame
frame "<!--framePath //<!--frame0-->-->" - didHandleOnloadEventsForFrame
frame "<!--framePath //<!--frame0-->-->" - didFinishLoadForFrame
main frame - didHandleOnloadEventsForFrame
main frame - didFinishLoadForFrame
ALERT: PASS: url fragment is changing asynchronously
ALERT: PASS: scheduled postMessage() before hashchange triggered.
frame "<!--framePath //<!--frame0-->-->" - didCommitLoadForFrame
ALERT: PASS: hashchange triggered after postMessage().
This tests that cross-origin fragment navigations are asynchronous. It does so by scheduling a postMessage before scheduling the navigation. If the navigation is synchronous, the frame load callback for the load's commit will happen before the message is handled. This isn't as flaky as it sounds, though it does rely on this postMessage behavior (which seems reasonable to do).
This test passes if the didChangeLocationWithinPageForFrame callback fires after the postMessage alert() fires.
This tests that cross-origin fragment navigations are asynchronous. It does so by scheduling a postMessage before scheduling the navigation. If the navigation is synchronous, the internals API will be able to report the presence of an url fragment immediately.
......@@ -3,7 +3,6 @@
<head>
<script>
if (window.testRunner) {
testRunner.dumpFrameLoadCallbacks();
testRunner.dumpAsText();
testRunner.waitUntilDone();
}
......@@ -11,6 +10,12 @@
function testFragmentNavigation() {
window.postMessage("postmessage", "*");
document.querySelector('iframe').src = "http://localhost:8000/navigation/resources/postmessage-on-hashchange.html#anchor1";
if (window.internals) {
if (internals.doesWindowHaveUrlFragment(document.querySelector('iframe').contentWindow))
alert("FAIL: url fragment should change asynchronously");
else
alert("PASS: url fragment is changing asynchronously");
}
}
var receivedScheduledPostMessage = false;
......@@ -36,11 +41,8 @@
<body>
<p>This tests that cross-origin fragment navigations are asynchronous. It does
so by scheduling a postMessage before scheduling the navigation. If the
navigation is synchronous, the frame load callback for the load's commit will
happen before the message is handled. This isn't as flaky as it sounds, though
it does rely on this postMessage behavior (which seems reasonable to do).</p>
<p>This test passes if the didChangeLocationWithinPageForFrame callback
fires after the postMessage alert() fires.</p>
navigation is synchronous, the internals API will be able to report the presence
of an url fragment immediately.</p>
<iframe src="http://localhost:8000/navigation/resources/postmessage-on-hashchange.html" onload='testFragmentNavigation()'></iframe>
</body>
</html>
frame "<!--framePath //<!--frame0-->-->" - didReceiveTitle:
frame "<!--framePath //<!--frame0-->-->" - didStartProvisionalLoadForFrame
main frame - didReceiveTitle:
main frame - didFinishDocumentLoadForFrame
frame "<!--framePath //<!--frame0-->-->" - didCommitLoadForFrame
frame "<!--framePath //<!--frame0-->-->" - didReceiveTitle:
frame "<!--framePath //<!--frame0-->-->" - didFinishDocumentLoadForFrame
frame "<!--framePath //<!--frame0-->-->" - didCommitLoadForFrame
frame "<!--framePath //<!--frame0-->-->" - didHandleOnloadEventsForFrame
frame "<!--framePath //<!--frame0-->-->" - didFinishLoadForFrame
main frame - didHandleOnloadEventsForFrame
main frame - didFinishLoadForFrame
ALERT: PASS: url fragment has changed synchronously
ALERT: PASS: scheduled postMessage() before hashchange triggered.
ALERT: PASS: hashchange triggered after postMessage().
This tests that same-origin fragment navigations are synchronous. It does so by scheduling a postMessage before scheduling the navigation. If the navigation is synchronous, the frame load callback for the load's commit will happen before the message is handled. This isn't as flaky as it sounds, though it does rely on this postMessage behavior (which seems reasonable to do).
This test passes if the didChangeLocationWithinPageForFrame callback fires before the postMessage alert() fires.
This tests that same-origin fragment navigations are synchronous. It does so by scheduling a postMessage before scheduling the navigation. If the navigation is synchronous, the internals API will be able to report the presence of an url fragment immediately.
......@@ -3,7 +3,6 @@
<head>
<script>
if (window.testRunner) {
testRunner.dumpFrameLoadCallbacks();
testRunner.dumpAsText();
testRunner.waitUntilDone();
}
......@@ -11,6 +10,12 @@
function testFragmentNavigation() {
window.postMessage("postmessage", "*");
document.querySelector('iframe').src = "http://127.0.0.1:8000/navigation/resources/postmessage-on-hashchange.html#anchor1";
if (window.internals) {
if (internals.doesWindowHaveUrlFragment(document.querySelector('iframe').contentWindow))
alert("PASS: url fragment has changed synchronously");
else
alert("FAIL: url fragment should change synchronously");
}
}
var receivedScheduledPostMessage = false;
......@@ -36,11 +41,8 @@
<body>
<p>This tests that same-origin fragment navigations are synchronous. It does
so by scheduling a postMessage before scheduling the navigation. If the
navigation is synchronous, the frame load callback for the load's commit will
happen before the message is handled. This isn't as flaky as it sounds, though
it does rely on this postMessage behavior (which seems reasonable to do).</p>
<p>This test passes if the didChangeLocationWithinPageForFrame callback
fires before the postMessage alert() fires.</p>
navigation is synchronous, the internals API will be able to report the presence
of an url fragment immediately.</p>
<iframe src="http://127.0.0.1:8000/navigation/resources/postmessage-on-hashchange.html" onload='testFragmentNavigation()'></iframe>
</body>
</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