| Index: content/browser/web_contents/opened_by_dom_browsertest.cc
|
| diff --git a/content/browser/web_contents/opened_by_dom_browsertest.cc b/content/browser/web_contents/opened_by_dom_browsertest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1c2d94099ce1d94e0d8c3fa126a974360f523b6a
|
| --- /dev/null
|
| +++ b/content/browser/web_contents/opened_by_dom_browsertest.cc
|
| @@ -0,0 +1,139 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "base/command_line.h"
|
| +#include "base/strings/stringprintf.h"
|
| +#include "content/public/browser/web_contents.h"
|
| +#include "content/public/browser/web_contents_delegate.h"
|
| +#include "content/public/common/content_switches.h"
|
| +#include "content/public/test/browser_test_utils.h"
|
| +#include "content/public/test/content_browser_test.h"
|
| +#include "content/public/test/content_browser_test_utils.h"
|
| +#include "content/public/test/test_navigation_observer.h"
|
| +#include "content/shell/browser/shell.h"
|
| +#include "net/dns/mock_host_resolver.h"
|
| +#include "url/gurl.h"
|
| +
|
| +namespace content {
|
| +
|
| +namespace {
|
| +
|
| +// A dummy WebContentsDelegate which tracks whether CloseContents() has been
|
| +// called. It refuses the actual close but keeps track of whether the renderer
|
| +// requested it.
|
| +class CloseTrackingDelegate : public WebContentsDelegate {
|
| + public:
|
| + CloseTrackingDelegate() : close_contents_called_(false) {}
|
| +
|
| + bool close_contents_called() const { return close_contents_called_; }
|
| +
|
| + virtual void CloseContents(WebContents* source) OVERRIDE {
|
| + close_contents_called_ = true;
|
| + }
|
| +
|
| + private:
|
| + bool close_contents_called_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(CloseTrackingDelegate);
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +class OpenedByDOMTest : public ContentBrowserTest {
|
| + protected:
|
| + virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
|
| + // Use --site-per-process to force process swaps on cross-site navigations.
|
| + command_line->AppendSwitch(switches::kSitePerProcess);
|
| + }
|
| +
|
| + bool AttemptCloseFromJavaScript(WebContents* web_contents) {
|
| + CloseTrackingDelegate close_tracking_delegate;
|
| + WebContentsDelegate* old_delegate = web_contents->GetDelegate();
|
| + web_contents->SetDelegate(&close_tracking_delegate);
|
| +
|
| + const char kCloseWindowScript[] =
|
| + // Close the window.
|
| + "window.close();"
|
| + // Report back after an event loop iteration; the close IPC isn't sent
|
| + // immediately.
|
| + "setTimeout(function() {"
|
| + "window.domAutomationController.send(0);"
|
| + "});";
|
| + int dummy;
|
| + CHECK(ExecuteScriptAndExtractInt(web_contents, kCloseWindowScript, &dummy));
|
| +
|
| + web_contents->SetDelegate(old_delegate);
|
| + return close_tracking_delegate.close_contents_called();
|
| + }
|
| +
|
| + Shell* OpenWindowFromJavaScript(Shell* shell, const GURL& url) {
|
| + // Wait for the popup to be created and for it to have navigated.
|
| + ShellAddedObserver new_shell_observer;
|
| + TestNavigationObserver nav_observer(NULL);
|
| + nav_observer.StartWatchingNewWebContents();
|
| + CHECK(ExecuteScript(
|
| + shell->web_contents(),
|
| + base::StringPrintf("window.open('%s')", url.spec().c_str())));
|
| + nav_observer.Wait();
|
| + return new_shell_observer.GetShell();
|
| + }
|
| +};
|
| +
|
| +// Tests that window.close() does not work on a normal window that has navigated
|
| +// a few times.
|
| +IN_PROC_BROWSER_TEST_F(OpenedByDOMTest, NormalWindow) {
|
| + ASSERT_TRUE(test_server()->Start());
|
| +
|
| + // window.close is allowed if the window was opened by DOM OR the back/forward
|
| + // list has only one element. Navigate a bit so the second condition is false.
|
| + GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1");
|
| + GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2");
|
| + NavigateToURL(shell(), url1);
|
| + NavigateToURL(shell(), url2);
|
| +
|
| + // This window was not opened by DOM, so close does not reach the browser
|
| + // process.
|
| + EXPECT_FALSE(AttemptCloseFromJavaScript(shell()->web_contents()));
|
| +}
|
| +
|
| +// Tests that window.close() works in a popup window that has navigated a few
|
| +// times.
|
| +IN_PROC_BROWSER_TEST_F(OpenedByDOMTest, Popup) {
|
| + ASSERT_TRUE(test_server()->Start());
|
| +
|
| + GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1");
|
| + GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2");
|
| + GURL url3 = test_server()->GetURL("files/site_isolation/blank.html?3");
|
| + NavigateToURL(shell(), url1);
|
| +
|
| + Shell* popup = OpenWindowFromJavaScript(shell(), url2);
|
| + NavigateToURL(popup, url3);
|
| + EXPECT_TRUE(AttemptCloseFromJavaScript(popup->web_contents()));
|
| +}
|
| +
|
| +// Tests that window.close() works in a popup window that has navigated a few
|
| +// times and swapped processes.
|
| +IN_PROC_BROWSER_TEST_F(OpenedByDOMTest, CrossProcessPopup) {
|
| + host_resolver()->AddRule("*", "127.0.0.1");
|
| + ASSERT_TRUE(test_server()->Start());
|
| +
|
| + GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1");
|
| +
|
| + GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2");
|
| + GURL::Replacements replace_host;
|
| + std::string foo_com("foo.com");
|
| + replace_host.SetHostStr(foo_com);
|
| + url2 = url2.ReplaceComponents(replace_host);
|
| +
|
| + GURL url3 = test_server()->GetURL("files/site_isolation/blank.html?3");
|
| + url3 = url3.ReplaceComponents(replace_host);
|
| +
|
| + NavigateToURL(shell(), url1);
|
| +
|
| + Shell* popup = OpenWindowFromJavaScript(shell(), url2);
|
| + NavigateToURL(popup, url3);
|
| + EXPECT_TRUE(AttemptCloseFromJavaScript(popup->web_contents()));
|
| +}
|
| +
|
| +} // namespace content
|
|
|