Commit 69ec73d0 authored by Lucas Furukawa Gadani's avatar Lucas Furukawa Gadani Committed by Commit Bot

Portals: Restrict portal navigations to HTTP family.

This is also enforced with a renderer kill in case the browser receives
a non-HTTP navigation request.

Bug: 962500
Change-Id: Id7c122ba80ef1cc00620d07d5ecdb1f268b04d79
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1615499
Commit-Queue: Lucas Gadani <lfg@chromium.org>
Reviewed-by: default avatarCharlie Reis <creis@chromium.org>
Reviewed-by: default avatarJeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#660918}
parent 4bfb3a11
......@@ -163,6 +163,15 @@ RenderFrameProxyHost* Portal::CreateProxyAndAttachPortal() {
}
void Portal::Navigate(const GURL& url) {
if (!url.SchemeIsHTTPOrHTTPS()) {
mojo::ReportBadMessage("Portal::Navigate tried to use non-HTTP protocol.");
binding_->Close(); // Also deletes |this|.
return;
}
// TODO(lfg): Investigate which other restrictions we might need when
// navigating portals. See http://crbug.com/964395.
NavigationController::LoadURLParams load_url_params(url);
portal_contents_impl_->GetController().LoadURLWithParams(load_url_params);
}
......
......@@ -22,6 +22,7 @@
#include "content/public/test/hit_test_region_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
......@@ -59,6 +60,15 @@ class PortalInterceptorForTesting final
portal_->Activate(std::move(data), std::move(callback));
}
void Navigate(const GURL& url) override {
if (navigate_callback_) {
navigate_callback_.Run(url);
return;
}
portal_->Navigate(url);
}
void WaitForActivate() {
if (portal_activated_)
return;
......@@ -72,6 +82,9 @@ class PortalInterceptorForTesting final
content::Portal* GetPortal() { return portal_.get(); }
WebContents* GetPortalContents() { return portal_->GetPortalContents(); }
// IPC callbacks
base::RepeatingCallback<void(const GURL&)> navigate_callback_;
private:
PortalInterceptorForTesting(RenderFrameHostImpl* render_frame_host_impl)
: portal_(content::Portal::CreateForTesting(render_frame_host_impl)) {}
......@@ -487,6 +500,39 @@ IN_PROC_BROWSER_TEST_F(PortalBrowserTest, AsyncEventTargetingIgnoresPortals) {
<< "Note: The portal's FrameSinkId is " << portal_view->GetFrameSinkId();
}
// Tests that trying to navigate to a chrome:// URL kills the renderer.
IN_PROC_BROWSER_TEST_F(PortalBrowserTest, NavigateToChrome) {
EXPECT_TRUE(NavigateToURL(
shell(), embedded_test_server()->GetURL("portal.test", "/title1.html")));
WebContentsImpl* web_contents_impl =
static_cast<WebContentsImpl*>(shell()->web_contents());
RenderFrameHostImpl* main_frame = web_contents_impl->GetMainFrame();
// Create portal.
PortalCreatedObserver portal_created_observer(main_frame);
EXPECT_TRUE(ExecJs(main_frame,
"var portal = document.createElement('portal');"
"document.body.appendChild(portal);"));
Portal* portal = portal_created_observer.WaitUntilPortalCreated();
PortalInterceptorForTesting* portal_interceptor =
PortalInterceptorForTesting::From(portal);
WebContentsImpl* portal_contents = portal->GetPortalContents();
// Try to navigate to chrome://settings and wait for the process to die.
portal_interceptor->navigate_callback_ = base::BindRepeating(
[](Portal* portal, const GURL& url) {
GURL chrome_url("chrome://settings");
portal->Navigate(chrome_url);
},
portal);
RenderProcessHostKillWaiter kill_waiter(
portal_contents->GetMainFrame()->GetProcess());
GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
EXPECT_TRUE(ExecJs(main_frame, JsReplace("portal.src = $1;", a_url)));
EXPECT_EQ(base::nullopt, kill_waiter.Wait());
}
class PortalOOPIFBrowserTest : public PortalBrowserTest {
protected:
PortalOOPIFBrowserTest() {}
......
......@@ -67,9 +67,18 @@ HTMLElement* HTMLPortalElement::Create(Document& document) {
void HTMLPortalElement::Navigate() {
KURL url = GetNonEmptyURLAttribute(html_names::kSrcAttr);
if (!url.IsEmpty() && portal_ptr_) {
portal_ptr_->Navigate(url);
if (!portal_ptr_ || url.IsEmpty())
return;
if (!url.ProtocolIsInHTTPFamily()) {
GetDocument().AddConsoleMessage(ConsoleMessage::Create(
mojom::ConsoleMessageSource::kRendering,
mojom::ConsoleMessageLevel::kWarning,
"Portals only allow navigation to protocols in the HTTP family."));
return;
}
portal_ptr_->Navigate(url);
}
void HTMLPortalElement::ConsumePortal() {
......
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