Chromium Code Reviews| Index: content/browser/security_exploit_browsertest.cc |
| diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc |
| index 2a1be07b9a9a34189f0747fcc329d36c1bd19ec9..68430ad3af7deebdfc00beefeb459d6157cad184 100644 |
| --- a/content/browser/security_exploit_browsertest.cc |
| +++ b/content/browser/security_exploit_browsertest.cc |
| @@ -4,14 +4,18 @@ |
| #include "base/command_line.h" |
| #include "base/containers/hash_tables.h" |
| +#include "base/strings/utf_string_conversions.h" |
| #include "content/browser/dom_storage/dom_storage_context_wrapper.h" |
| #include "content/browser/dom_storage/session_storage_namespace_impl.h" |
| #include "content/browser/frame_host/navigator.h" |
| #include "content/browser/renderer_host/render_view_host_factory.h" |
| #include "content/browser/renderer_host/render_view_host_impl.h" |
| #include "content/browser/web_contents/web_contents_impl.h" |
| +#include "content/common/frame_messages.h" |
| #include "content/common/view_messages.h" |
| #include "content/public/browser/browser_context.h" |
| +#include "content/public/browser/interstitial_page.h" |
| +#include "content/public/browser/interstitial_page_delegate.h" |
| #include "content/public/browser/storage_partition.h" |
| #include "content/public/common/content_switches.h" |
| #include "content/public/test/browser_test_utils.h" |
| @@ -19,6 +23,11 @@ |
| #include "content/public/test/content_browser_test_utils.h" |
| #include "content/public/test/test_utils.h" |
| #include "content/shell/browser/shell.h" |
| +#include "ipc/ipc_security_test_util.h" |
| +#include "net/dns/mock_host_resolver.h" |
| +#include "net/test/embedded_test_server/embedded_test_server.h" |
| + |
| +using IPC::IpcSecurityTestUtil; |
| namespace content { |
| @@ -35,10 +44,11 @@ namespace { |
| // the attempt is the return value. |
| RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell, |
| int* target_routing_id) { |
| - GURL foo("http://foo.com/files/simple_page.html"); |
| + GURL foo("http://foo.com/simple_page.html"); |
| // Start off with initial navigation, so we get the first process allocated. |
| NavigateToURL(shell, foo); |
| + EXPECT_EQ(base::ASCIIToUTF16("OK"), shell->web_contents()->GetTitle()); |
|
Charlie Reis
2014/11/14 00:13:27
I think we can put EXPECT_TRUE on the NavigateToUR
|
| // Open another window, so we generate some more routing ids. |
| ShellAddedObserver shell2_observer; |
| @@ -55,7 +65,7 @@ RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell, |
| shell->web_contents()->GetRenderViewHost()->GetRoutingID()); |
| // Now, simulate a link click coming from the renderer. |
| - GURL extension_url("https://bar.com/files/simple_page.html"); |
| + GURL extension_url("https://bar.com/simple_page.html"); |
| WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell->web_contents()); |
| wc->GetFrameTree()->root()->navigator()->RequestOpenURL( |
| wc->GetFrameTree()->root()->current_frame_host(), extension_url, |
| @@ -84,25 +94,37 @@ RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell, |
| class SecurityExploitBrowserTest : public ContentBrowserTest { |
| public: |
| SecurityExploitBrowserTest() {} |
| + |
| void SetUpCommandLine(CommandLine* command_line) override { |
| - ASSERT_TRUE(test_server()->Start()); |
| + ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); |
| // Add a host resolver rule to map all outgoing requests to the test server. |
| // This allows us to use "real" hostnames in URLs, which we can use to |
| // create arbitrary SiteInstances. |
| command_line->AppendSwitchASCII( |
| switches::kHostResolverRules, |
| - "MAP * " + test_server()->host_port_pair().ToString() + |
| + "MAP * " + |
| + net::HostPortPair::FromURL(embedded_test_server()->base_url()) |
| + .ToString() + |
| ",EXCLUDE localhost"); |
| } |
| }; |
| +// Fails because the process kill on Android does not succeed. |
| +// http://crbug.com/433068 |
| +#if defined(OS_ANDROID) |
| +#define MAYBE_SetWebUIProperty DISABLED_SetWebUIProperty |
| +#else |
| +#define MAYBE_SetWebUIProperty SetWebUIProperty |
| +#endif |
| + |
| // Ensure that we kill the renderer process if we try to give it WebUI |
| // properties and it doesn't have enabled WebUI bindings. |
| -IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, SetWebUIProperty) { |
| - GURL foo("http://foo.com/files/simple_page.html"); |
| +IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, MAYBE_SetWebUIProperty) { |
| + GURL foo("http://foo.com/simple_page.html"); |
| NavigateToURL(shell(), foo); |
| + EXPECT_EQ(base::ASCIIToUTF16("OK"), shell()->web_contents()->GetTitle()); |
| EXPECT_EQ(0, |
| shell()->web_contents()->GetRenderViewHost()->GetEnabledBindings()); |
| @@ -166,4 +188,97 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, |
| // If the above operation doesn't crash, the test has succeeded! |
| } |
| +class SecurityExploitTestInterstitialPage : public InterstitialPageDelegate { |
| + public: |
| + explicit SecurityExploitTestInterstitialPage(WebContents* contents) { |
| + InterstitialPage* interstitial = InterstitialPage::Create( |
| + contents, true, contents->GetLastCommittedURL(), this); |
| + interstitial->Show(); |
| + } |
| + |
| + // InterstitialPageDelegate implementation. |
| + void CommandReceived(const std::string& command) override { |
| + last_command_ = command; |
| + } |
| + |
| + std::string GetHTMLContents() override { |
| + return "<html><head><script>" |
| + "window.domAutomationController.setAutomationId(1);" |
| + "window.domAutomationController.send(\"okay\");" |
| + "</script></head>" |
| + "<body>this page is an interstitial</body></html>"; |
| + } |
| + |
| + std::string last_command() { return last_command_; } |
| + |
| + private: |
| + std::string last_command_; |
| + DISALLOW_COPY_AND_ASSIGN(SecurityExploitTestInterstitialPage); |
| +}; |
| + |
| +// Fails due to InterstitialPage's reliance on PostNonNestableTask |
| +// http://crbug.com/432737 |
| +#if defined(OS_ANDROID) |
| +#define MAYBE_InterstitialCommandFromUnderlyingContent \ |
| + DISABLED_InterstitialCommandFromUnderlyingContent |
| +#else |
| +#define MAYBE_InterstitialCommandFromUnderlyingContent \ |
| + InterstitialCommandFromUnderlyingContent |
| +#endif |
| + |
| +// The interstitial should not be controllable by the underlying content. |
| +IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, |
| + MAYBE_InterstitialCommandFromUnderlyingContent) { |
| + // Start off with initial navigation, to allocate the process. |
| + GURL foo("http://foo.com/simple_page.html"); |
| + NavigateToURL(shell(), foo); |
| + EXPECT_EQ(base::ASCIIToUTF16("OK"), shell()->web_contents()->GetTitle()); |
| + |
| + DOMMessageQueue message_queue; |
| + |
| + // Install and show an interstitial page. |
| + SecurityExploitTestInterstitialPage* interstitial = |
| + new SecurityExploitTestInterstitialPage(shell()->web_contents()); |
| + |
| + ASSERT_EQ("", interstitial->last_command()); |
| + content::WaitForInterstitialAttach(shell()->web_contents()); |
| + |
| + InterstitialPage* interstitial_page = |
| + shell()->web_contents()->GetInterstitialPage(); |
| + ASSERT_TRUE(interstitial_page != NULL); |
| + ASSERT_TRUE(shell()->web_contents()->ShowingInterstitialPage()); |
| + ASSERT_TRUE(interstitial_page->GetDelegateForTesting() == interstitial); |
|
Charlie Reis
2014/11/14 00:13:27
nit: ASSERT_EQ
|
| + |
| + // The interstitial page ought to be able to send a message. |
| + std::string message; |
| + ASSERT_TRUE(message_queue.WaitForMessage(&message)); |
| + ASSERT_EQ("\"okay\"", message); |
| + ASSERT_EQ("\"okay\"", interstitial->last_command()); |
| + |
| + // Send an automation message from the underlying content and wait for it to |
| + // be dispatched on this thread. This message should not be received by the |
| + // interstitial. |
| + content::RenderFrameHost* compromised_renderer = |
| + shell()->web_contents()->GetMainFrame(); |
| + FrameHostMsg_DomOperationResponse evil(compromised_renderer->GetRoutingID(), |
| + "evil", MSG_ROUTING_NONE); |
| + IpcSecurityTestUtil::PwnMessageReceived( |
| + compromised_renderer->GetProcess()->GetChannel(), evil); |
| + |
| + ASSERT_TRUE(message_queue.WaitForMessage(&message)); |
| + ASSERT_EQ("evil", message) |
| + << "Automation message should be received by WebContents."; |
| + ASSERT_EQ("\"okay\"", interstitial->last_command()) |
| + << "Interstitial should not be affected."; |
| + |
| + // Send a second message from the interstitial page, and make sure that the |
| + // "evil" message doesn't arrive in the intervening period. |
| + ASSERT_TRUE(content::ExecuteScript( |
| + interstitial_page->GetRenderViewHostForTesting(), |
| + "window.domAutomationController.send(\"okay2\");")); |
| + ASSERT_TRUE(message_queue.WaitForMessage(&message)); |
| + ASSERT_EQ("\"okay2\"", message); |
| + ASSERT_EQ("\"okay2\"", interstitial->last_command()); |
| +} |
| + |
| } // namespace content |