Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / browser / web_contents / opened_by_dom_browsertest.cc
blobdab6eb8d3180845a63c920b7e0003dd9e724d31d
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.
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"
18 namespace content {
20 namespace {
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.
25 class CloseTrackingDelegate : public WebContentsDelegate {
26 public:
27 CloseTrackingDelegate() : close_contents_called_(false) {}
29 bool close_contents_called() const { return close_contents_called_; }
31 void CloseContents(WebContents* source) override {
32 close_contents_called_ = true;
35 private:
36 bool close_contents_called_;
38 DISALLOW_COPY_AND_ASSIGN(CloseTrackingDelegate);
41 } // namespace
43 class OpenedByDOMTest : public ContentBrowserTest {
44 protected:
45 void SetUpCommandLine(base::CommandLine* command_line) override {
46 // Use --site-per-process to force process swaps on cross-site navigations.
47 command_line->AppendSwitch(switches::kSitePerProcess);
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);
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));
66 web_contents->SetDelegate(old_delegate);
67 return close_tracking_delegate.close_contents_called();
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();
83 // Tests that window.close() does not work on a normal window that has navigated
84 // a few times.
85 IN_PROC_BROWSER_TEST_F(OpenedByDOMTest, NormalWindow) {
86 ASSERT_TRUE(test_server()->Start());
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);
95 // This window was not opened by DOM, so close does not reach the browser
96 // process.
97 EXPECT_FALSE(AttemptCloseFromJavaScript(shell()->web_contents()));
100 // Tests that window.close() works in a popup window that has navigated a few
101 // times.
102 IN_PROC_BROWSER_TEST_F(OpenedByDOMTest, Popup) {
103 ASSERT_TRUE(test_server()->Start());
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);
110 Shell* popup = OpenWindowFromJavaScript(shell(), url2);
111 NavigateToURL(popup, url3);
112 EXPECT_TRUE(AttemptCloseFromJavaScript(popup->web_contents()));
115 // Tests that window.close() works in a popup window that has navigated a few
116 // times and swapped processes.
117 // Crashes on all platforms. http://crbug.com/399709
118 IN_PROC_BROWSER_TEST_F(OpenedByDOMTest, DISABLED_CrossProcessPopup) {
119 host_resolver()->AddRule("*", "127.0.0.1");
120 ASSERT_TRUE(test_server()->Start());
122 GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1");
124 GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2");
125 GURL::Replacements replace_host;
126 replace_host.SetHostStr("foo.com");
127 url2 = url2.ReplaceComponents(replace_host);
129 GURL url3 = test_server()->GetURL("files/site_isolation/blank.html?3");
130 url3 = url3.ReplaceComponents(replace_host);
132 NavigateToURL(shell(), url1);
134 Shell* popup = OpenWindowFromJavaScript(shell(), url2);
135 NavigateToURL(popup, url3);
136 EXPECT_TRUE(AttemptCloseFromJavaScript(popup->web_contents()));
139 } // namespace content