Skip to content

Commit

Permalink
Block renderer-initiated main frame navigations to data URLs
Browse files Browse the repository at this point in the history
This CL implements the blocking of data URL navigations as described in the
blink intent to deprecate and remove thread at https://goo.gl/BaZAea.

The blocking is done in two separate places:

- blink::FrameLoader: This is a renderer side check that blocks all top-frame
  loads for known mime types. This check ignores unknown mime types as those
  can end up as downloads or be handled by plugins.

- content::DataURLNavigationThrottler: This is a browser side check that
  handles data URLs that were ignored by the renderer check. By this point, the
  determination of whether the URL is a download or not has already been made.
  This check allows downloads and blocks remaining URLs (ie. mime types that
  are handled by plugins). When browser side navigation is enabled, all blocking
  is done in this throttler instead of some checks being in blink::FrameLoader.

This CL moves data URL navigation tests to a separate file, and removes layout
tests that are no longer realistic.

TEST=data_url_navigation_browsertest.cc
BUG=594215
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:linux_site_isolation

Review-Url: https://codereview.chromium.org/2702503002
Cr-Commit-Position: refs/heads/master@{#466504}
  • Loading branch information
meacer authored and Commit bot committed Apr 22, 2017
1 parent 8ee6041 commit ba52f56
Show file tree
Hide file tree
Showing 46 changed files with 1,340 additions and 251 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public boolean isSatisfied() {
@Override
public boolean isSatisfied() {
if (getNumInfobarsShowing() != 0) return false;
return TextUtils.equals("Popup #3", selector.getCurrentTab().getTitle());
return TextUtils.equals("Three", selector.getCurrentTab().getTitle());
}
}, 7500, CriteriaHelper.DEFAULT_POLLING_INTERVAL);

Expand All @@ -126,7 +126,7 @@ public boolean isSatisfied() {
public boolean isSatisfied() {
if (getNumInfobarsShowing() != 0) return false;
if (selector.getTotalTabCount() != 7) return false;
return TextUtils.equals("Popup #3", selector.getCurrentTab().getTitle());
return TextUtils.equals("Three", selector.getCurrentTab().getTitle());
}
}, 7500, CriteriaHelper.DEFAULT_POLLING_INTERVAL);
assertNotSame(currentTabId, selector.getCurrentTab().getId());
Expand Down
6 changes: 6 additions & 0 deletions chrome/browser/apps/guest_view/web_view_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1298,6 +1298,12 @@ IN_PROC_BROWSER_TEST_P(WebViewTest,
NO_TEST_SERVER);
}

IN_PROC_BROWSER_TEST_P(WebViewTest,
Shim_TestContentInitiatedNavigationToDataUrlBlocked) {
TestHelper("testContentInitiatedNavigationToDataUrlBlocked", "web_view/shim",
NO_TEST_SERVER);
}

IN_PROC_BROWSER_TEST_P(WebViewTest, Shim_TestDisplayNoneWebviewLoad) {
TestHelper("testDisplayNoneWebviewLoad", "web_view/shim", NO_TEST_SERVER);
}
Expand Down
2 changes: 2 additions & 0 deletions chrome/browser/tab_contents/navigation_metrics_recorder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ void NavigationMetricsRecorder::DidFinishNavigation(
!ui::PageTransitionCoreTypeIs(navigation_handle->GetPageTransition(),
ui::PAGE_TRANSITION_TYPED)) {
if (!navigation_handle->GetPreviousURL().is_empty()) {
// TODO(meacer): Remove once data URL navigations are blocked.
rappor::SampleDomainAndRegistryFromGURL(
rappor_service_, "Navigation.Scheme.Data",
navigation_handle->GetPreviousURL());
Expand All @@ -96,6 +97,7 @@ void NavigationMetricsRecorder::DidFinishNavigation(
// Also record the mime type of the data: URL.
std::string mime_type;
std::string charset;
// TODO(meacer): Remove once data URL navigations are blocked.
if (net::DataURL::Parse(last_committed_entry->GetVirtualURL(), &mime_type,
&charset, nullptr)) {
RecordDataURLMimeType(mime_type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,6 @@ namespace {

typedef InProcessBrowserTest NavigationMetricsRecorderBrowserTest;

// Performs a content initiated navigation to |url|.
void RedirectToUrl(content::WebContents* web_contents, const GURL& url) {
content::TestNavigationObserver observer(web_contents, 1);
EXPECT_TRUE(content::ExecuteScript(
web_contents, std::string("window.location.href='") + url.spec() + "'"));
observer.Wait();
}

IN_PROC_BROWSER_TEST_F(NavigationMetricsRecorderBrowserTest, TestMetrics) {
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
Expand All @@ -46,79 +38,54 @@ IN_PROC_BROWSER_TEST_F(NavigationMetricsRecorderBrowserTest, TestMetrics) {
5 /* data: */, 1);
// Since there was no previous URL, Rappor shouldn't record anything.
EXPECT_EQ(0, rappor_service.GetReportsCount());

// Navigate to an empty page and redirect it to a data: URL. Rappor should
// record a report.
ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
content::TestNavigationObserver observer(web_contents, 1);
EXPECT_TRUE(content::ExecuteScript(
web_contents, "window.location.href='data:text/html, <html></html>'"));
observer.Wait();

EXPECT_EQ(1, rappor_service.GetReportsCount());
std::string sample;
rappor::RapporType type;
EXPECT_TRUE(rappor_service.GetRecordedSampleForMetric(
"Navigation.Scheme.Data", &sample, &type));
EXPECT_EQ("about://", sample);
EXPECT_EQ(rappor::ETLD_PLUS_ONE_RAPPOR_TYPE, type);
}

IN_PROC_BROWSER_TEST_F(NavigationMetricsRecorderBrowserTest, DataURLMimeTypes) {
base::HistogramTester histograms;
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();

// HTML:
RedirectToUrl(web_contents, GURL("data:text/html, <html></html>"));
ui_test_utils::NavigateToURL(browser(),
GURL("data:text/html, <html></html>"));
histograms.ExpectTotalCount("Navigation.MainFrameScheme", 1);
histograms.ExpectBucketCount("Navigation.MainFrameScheme", 5 /* data: */, 1);
histograms.ExpectTotalCount("Navigation.MainFrameSchemeDifferentPage", 1);
histograms.ExpectBucketCount("Navigation.MainFrameSchemeDifferentPage",
5 /* data: */, 1);
histograms.ExpectTotalCount("Navigation.MainFrameScheme.DataUrl.MimeType", 1);
histograms.ExpectBucketCount("Navigation.MainFrameScheme.DataUrl.MimeType",
NavigationMetricsRecorder::MIME_TYPE_HTML, 1);
histograms.ExpectTotalCount("Navigation.MainFrameScheme.DataUrl.MimeType", 0);

// SVG:
RedirectToUrl(web_contents,
GURL("data:image/svg+xml,<!DOCTYPE svg><svg version=\"1.1\" "
"xmlns=\"http://www.w3.org/2000/svg\"></svg>"));
ui_test_utils::NavigateToURL(
browser(), GURL("data:image/svg+xml,<!DOCTYPE svg><svg version=\"1.1\" "
"xmlns=\"http://www.w3.org/2000/svg\"></svg>"));
histograms.ExpectTotalCount("Navigation.MainFrameScheme", 2);
histograms.ExpectBucketCount("Navigation.MainFrameScheme", 5 /* data: */, 2);
histograms.ExpectTotalCount("Navigation.MainFrameSchemeDifferentPage", 2);
histograms.ExpectBucketCount("Navigation.MainFrameSchemeDifferentPage",
5 /* data: */, 2);
histograms.ExpectTotalCount("Navigation.MainFrameScheme.DataUrl.MimeType", 2);
histograms.ExpectBucketCount("Navigation.MainFrameScheme.DataUrl.MimeType",
NavigationMetricsRecorder::MIME_TYPE_SVG, 1);
histograms.ExpectTotalCount("Navigation.MainFrameScheme.DataUrl.MimeType", 0);

// Base64 encoded HTML:
RedirectToUrl(web_contents,
GURL("data:text/html;base64, PGh0bWw+YmFzZTY0PC9odG1sPg=="));
ui_test_utils::NavigateToURL(
browser(), GURL("data:text/html;base64, PGh0bWw+YmFzZTY0PC9odG1sPg=="));
histograms.ExpectTotalCount("Navigation.MainFrameScheme", 3);
histograms.ExpectBucketCount("Navigation.MainFrameScheme", 5 /* data: */, 3);
histograms.ExpectTotalCount("Navigation.MainFrameSchemeDifferentPage", 3);
histograms.ExpectBucketCount("Navigation.MainFrameSchemeDifferentPage",
5 /* data: */, 3);
histograms.ExpectTotalCount("Navigation.MainFrameScheme.DataUrl.MimeType", 3);
histograms.ExpectBucketCount("Navigation.MainFrameScheme.DataUrl.MimeType",
NavigationMetricsRecorder::MIME_TYPE_HTML, 2);
histograms.ExpectTotalCount("Navigation.MainFrameScheme.DataUrl.MimeType", 0);

// Plain text:
RedirectToUrl(web_contents, GURL("data:text/plain, test"));
ui_test_utils::NavigateToURL(browser(), GURL("data:text/plain, test"));
histograms.ExpectTotalCount("Navigation.MainFrameScheme", 4);
histograms.ExpectBucketCount("Navigation.MainFrameScheme", 5 /* data: */, 4);
histograms.ExpectTotalCount("Navigation.MainFrameSchemeDifferentPage", 4);
histograms.ExpectBucketCount("Navigation.MainFrameSchemeDifferentPage",
5 /* data: */, 4);
histograms.ExpectTotalCount("Navigation.MainFrameScheme.DataUrl.MimeType", 4);
histograms.ExpectBucketCount("Navigation.MainFrameScheme.DataUrl.MimeType",
NavigationMetricsRecorder::MIME_TYPE_OTHER, 1);
histograms.ExpectTotalCount("Navigation.MainFrameScheme.DataUrl.MimeType", 0);

// Base64 encoded PNG:
RedirectToUrl(
web_contents,
ui_test_utils::NavigateToURL(
browser(),
GURL("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA"
"AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO"
"9TXL0Y4OHwAAAABJRU5ErkJggg=="));
Expand All @@ -127,9 +94,7 @@ IN_PROC_BROWSER_TEST_F(NavigationMetricsRecorderBrowserTest, DataURLMimeTypes) {
histograms.ExpectTotalCount("Navigation.MainFrameSchemeDifferentPage", 5);
histograms.ExpectBucketCount("Navigation.MainFrameSchemeDifferentPage",
5 /* data: */, 5);
histograms.ExpectTotalCount("Navigation.MainFrameScheme.DataUrl.MimeType", 5);
histograms.ExpectBucketCount("Navigation.MainFrameScheme.DataUrl.MimeType",
NavigationMetricsRecorder::MIME_TYPE_OTHER, 2);
histograms.ExpectTotalCount("Navigation.MainFrameScheme.DataUrl.MimeType", 0);
}

} // namespace
6 changes: 3 additions & 3 deletions chrome/test/data/android/popup_test.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
<title>Popup test page</title>
<script type="text/javascript">
function spawnWindows() {
window.open('data:text/html,<html><head><title>Popup #1</title></head><body /></html>');
window.open('data:text/html,<html><head><title>Popup #2</title></head><body /></html>');
window.open('data:text/html,<html><head><title>Popup #3</title></head><body /></html>');
window.open('navigate/one.html');
window.open('navigate/two.html');
window.open('navigate/three.html');
}
</script>
</head>
Expand Down
24 changes: 24 additions & 0 deletions chrome/test/data/extensions/platform_apps/web_view/shim/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,28 @@ function testChromeExtensionRelativePath() {
document.body.appendChild(webview);
}

// This test verifies that guests are blocked from navigating the webview to a
// data URL.
function testContentInitiatedNavigationToDataUrlBlocked() {
var navUrl = "data:text/html,foo";
var webview = document.createElement('webview');
webview.addEventListener('consolemessage', function(e) {
if (e.message.startsWith(
'Not allowed to navigate top frame to data URL:')) {
embedder.test.succeed();
}
});
webview.addEventListener('loadstop', function(e) {
if (webview.getAttribute('src') == navUrl) {
embedder.test.fail();
}
});
webview.setAttribute('src',
'data:text/html,<script>window.location.href = "' + navUrl +
'";</scr' + 'ipt>');
document.body.appendChild(webview);
}

// Tests that a <webview> that starts with "display: none" style loads
// properly.
function testDisplayNoneWebviewLoad() {
Expand Down Expand Up @@ -3076,6 +3098,8 @@ embedder.test.testList = {
'testAddAndRemoveContentScripts': testAddAndRemoveContentScripts,
'testAddContentScriptsWithNewWindowAPI':
testAddContentScriptsWithNewWindowAPI,
'testContentInitiatedNavigationToDataUrlBlocked':
testContentInitiatedNavigationToDataUrlBlocked,
'testContentScriptIsInjectedAfterTerminateAndReloadWebView':
testContentScriptIsInjectedAfterTerminateAndReloadWebView,
'testContentScriptExistsAsLongAsWebViewTagExists':
Expand Down
2 changes: 2 additions & 0 deletions content/browser/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,8 @@ source_set("browser") {
"frame_host/ancestor_throttle.h",
"frame_host/cross_process_frame_connector.cc",
"frame_host/cross_process_frame_connector.h",
"frame_host/data_url_navigation_throttle.cc",
"frame_host/data_url_navigation_throttle.h",
"frame_host/debug_urls.cc",
"frame_host/debug_urls.h",
"frame_host/form_submission_throttle.cc",
Expand Down
Loading

0 comments on commit ba52f56

Please sign in to comment.