opened_by_dom_browsertest.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/command_line.h" 6#include "base/strings/stringprintf.h" 7#include "content/public/browser/web_contents.h" 8#include "content/public/browser/web_contents_delegate.h" 9#include "content/public/common/content_switches.h" 10#include "content/public/test/browser_test_utils.h" 11#include "content/public/test/content_browser_test.h" 12#include "content/public/test/content_browser_test_utils.h" 13#include "content/public/test/test_navigation_observer.h" 14#include "content/shell/browser/shell.h" 15#include "net/dns/mock_host_resolver.h" 16#include "url/gurl.h" 17 18namespace content { 19 20namespace { 21 22// A dummy WebContentsDelegate which tracks whether CloseContents() has been 23// called. It refuses the actual close but keeps track of whether the renderer 24// requested it. 25class CloseTrackingDelegate : public WebContentsDelegate { 26 public: 27 CloseTrackingDelegate() : close_contents_called_(false) {} 28 29 bool close_contents_called() const { return close_contents_called_; } 30 31 virtual void CloseContents(WebContents* source) OVERRIDE { 32 close_contents_called_ = true; 33 } 34 35 private: 36 bool close_contents_called_; 37 38 DISALLOW_COPY_AND_ASSIGN(CloseTrackingDelegate); 39}; 40 41} // namespace 42 43class OpenedByDOMTest : public ContentBrowserTest { 44 protected: 45 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 46 // Use --site-per-process to force process swaps on cross-site navigations. 47 command_line->AppendSwitch(switches::kSitePerProcess); 48 } 49 50 bool AttemptCloseFromJavaScript(WebContents* web_contents) { 51 CloseTrackingDelegate close_tracking_delegate; 52 WebContentsDelegate* old_delegate = web_contents->GetDelegate(); 53 web_contents->SetDelegate(&close_tracking_delegate); 54 55 const char kCloseWindowScript[] = 56 // Close the window. 57 "window.close();" 58 // Report back after an event loop iteration; the close IPC isn't sent 59 // immediately. 60 "setTimeout(function() {" 61 "window.domAutomationController.send(0);" 62 "});"; 63 int dummy; 64 CHECK(ExecuteScriptAndExtractInt(web_contents, kCloseWindowScript, &dummy)); 65 66 web_contents->SetDelegate(old_delegate); 67 return close_tracking_delegate.close_contents_called(); 68 } 69 70 Shell* OpenWindowFromJavaScript(Shell* shell, const GURL& url) { 71 // Wait for the popup to be created and for it to have navigated. 72 ShellAddedObserver new_shell_observer; 73 TestNavigationObserver nav_observer(NULL); 74 nav_observer.StartWatchingNewWebContents(); 75 CHECK(ExecuteScript( 76 shell->web_contents(), 77 base::StringPrintf("window.open('%s')", url.spec().c_str()))); 78 nav_observer.Wait(); 79 return new_shell_observer.GetShell(); 80 } 81}; 82 83// Tests that window.close() does not work on a normal window that has navigated 84// a few times. 85IN_PROC_BROWSER_TEST_F(OpenedByDOMTest, NormalWindow) { 86 ASSERT_TRUE(test_server()->Start()); 87 88 // window.close is allowed if the window was opened by DOM OR the back/forward 89 // list has only one element. Navigate a bit so the second condition is false. 90 GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1"); 91 GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2"); 92 NavigateToURL(shell(), url1); 93 NavigateToURL(shell(), url2); 94 95 // This window was not opened by DOM, so close does not reach the browser 96 // process. 97 EXPECT_FALSE(AttemptCloseFromJavaScript(shell()->web_contents())); 98} 99 100// Tests that window.close() works in a popup window that has navigated a few 101// times. 102IN_PROC_BROWSER_TEST_F(OpenedByDOMTest, Popup) { 103 ASSERT_TRUE(test_server()->Start()); 104 105 GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1"); 106 GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2"); 107 GURL url3 = test_server()->GetURL("files/site_isolation/blank.html?3"); 108 NavigateToURL(shell(), url1); 109 110 Shell* popup = OpenWindowFromJavaScript(shell(), url2); 111 NavigateToURL(popup, url3); 112 EXPECT_TRUE(AttemptCloseFromJavaScript(popup->web_contents())); 113} 114 115// Tests that window.close() works in a popup window that has navigated a few 116// times and swapped processes. 117IN_PROC_BROWSER_TEST_F(OpenedByDOMTest, CrossProcessPopup) { 118 host_resolver()->AddRule("*", "127.0.0.1"); 119 ASSERT_TRUE(test_server()->Start()); 120 121 GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1"); 122 123 GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2"); 124 GURL::Replacements replace_host; 125 std::string foo_com("foo.com"); 126 replace_host.SetHostStr(foo_com); 127 url2 = url2.ReplaceComponents(replace_host); 128 129 GURL url3 = test_server()->GetURL("files/site_isolation/blank.html?3"); 130 url3 = url3.ReplaceComponents(replace_host); 131 132 NavigateToURL(shell(), url1); 133 134 Shell* popup = OpenWindowFromJavaScript(shell(), url2); 135 NavigateToURL(popup, url3); 136 EXPECT_TRUE(AttemptCloseFromJavaScript(popup->web_contents())); 137} 138 139} // namespace content 140