summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralexmos <alexmos@chromium.org>2015-07-15 16:40:43 -0700
committerCommit bot <commit-bot@chromium.org>2015-07-15 23:42:23 +0000
commit4cf2aa39e2220a3b5ef50a95fc11cf4ff35a85d5 (patch)
tree66cc445ac5ef2ec333a3f1f7441e6cd86fb6739e
parent197e83066dc598fb0b78f83d8e98ba445f990c43 (diff)
downloadchromium_src-4cf2aa39e2220a3b5ef50a95fc11cf4ff35a85d5.zip
chromium_src-4cf2aa39e2220a3b5ef50a95fc11cf4ff35a85d5.tar.gz
chromium_src-4cf2aa39e2220a3b5ef50a95fc11cf4ff35a85d5.tar.bz2
OOPIF: Fix window.open to work from frames with remote parent.
This CL addresses these remaining issues with that scenario: 1. WebContentsImpl::CreateNewWindow kills a renderer opening a new window if the renderer's process doesn't match the process for WebContents' main frame. This CL modifies this check to instead look at all renderer processes under the current WebContents. 2. The popup was getting created in the wrong SiteInstance, always using the SiteInstance of the WebContents' main frame rather than the SiteInstance of the source frame. This CL fixes this by plumbing the source frame's SiteInstance into WebContentsImpl::CreateNewWindow. 3. Once created, the popup wasn't being shown. This is because the message to show it (ViewHostMsg_ShowView) is sent via the opener's RenderView, which in this case is swapped out. This caused RenderViewHostImpl::OnShowView to exit early because it checked is_active_. To fix this, this CL removes this check from ShowView. Eventually, this IPC should be moved to RenderFrameHost. BUG=463949,225940 Review URL: https://codereview.chromium.org/1224363002 Cr-Commit-Position: refs/heads/master@{#338949}
-rw-r--r--content/browser/frame_host/interstitial_page_impl.cc2
-rw-r--r--content/browser/frame_host/interstitial_page_impl.h2
-rw-r--r--content/browser/frame_host/render_frame_host_manager_browsertest.cc29
-rw-r--r--content/browser/renderer_host/render_view_host_delegate.h12
-rw-r--r--content/browser/renderer_host/render_view_host_impl.cc11
-rw-r--r--content/browser/site_per_process_browsertest.cc65
-rw-r--r--content/browser/web_contents/web_contents_impl.cc36
-rw-r--r--content/browser/web_contents/web_contents_impl.h2
-rw-r--r--content/content_tests.gypi4
-rw-r--r--content/public/test/browser_test_utils.cc12
-rw-r--r--content/public/test/browser_test_utils.h10
-rw-r--r--content/test/BUILD.gn2
-rw-r--r--content/test/content_browser_test_utils_internal.cc21
-rw-r--r--content/test/content_browser_test_utils_internal.h11
-rw-r--r--content/test/test_web_contents.cc2
-rw-r--r--content/test/test_web_contents.h2
16 files changed, 162 insertions, 61 deletions
diff --git a/content/browser/frame_host/interstitial_page_impl.cc b/content/browser/frame_host/interstitial_page_impl.cc
index f622283..d769c4d 100644
--- a/content/browser/frame_host/interstitial_page_impl.cc
+++ b/content/browser/frame_host/interstitial_page_impl.cc
@@ -755,7 +755,7 @@ gfx::Rect InterstitialPageImpl::GetRootWindowResizerRect() const {
}
void InterstitialPageImpl::CreateNewWindow(
- int render_process_id,
+ SiteInstance* source_site_instance,
int route_id,
int main_frame_route_id,
const ViewHostMsg_CreateWindow_Params& params,
diff --git a/content/browser/frame_host/interstitial_page_impl.h b/content/browser/frame_host/interstitial_page_impl.h
index 3cbad79..2acb6e5 100644
--- a/content/browser/frame_host/interstitial_page_impl.h
+++ b/content/browser/frame_host/interstitial_page_impl.h
@@ -122,7 +122,7 @@ class CONTENT_EXPORT InterstitialPageImpl
BrowserContext* browser_context) const override;
gfx::Rect GetRootWindowResizerRect() const override;
void CreateNewWindow(
- int render_process_id,
+ SiteInstance* source_site_instance,
int route_id,
int main_frame_route_id,
const ViewHostMsg_CreateWindow_Params& params,
diff --git a/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
index f626fc7..19e81a0 100644
--- a/content/browser/frame_host/render_frame_host_manager_browsertest.cc
+++ b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -37,6 +37,7 @@
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test_utils_internal.h"
#include "net/base/net_util.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@@ -58,25 +59,11 @@ const char kOpenUrlViaClickTargetFunc[] =
"})";
// Adds a link with given url and target=_blank, and clicks on it.
-void OpenUrlViaClickTarget(const internal::ToRenderFrameHost& adapter,
- const GURL& url) {
+void OpenUrlViaClickTarget(const ToRenderFrameHost& adapter, const GURL& url) {
EXPECT_TRUE(ExecuteScript(adapter,
std::string(kOpenUrlViaClickTargetFunc) + "(\"" + url.spec() + "\");"));
}
-Shell* OpenPopup(const internal::ToRenderFrameHost& opener,
- const std::string& name) {
- ShellAddedObserver new_shell_observer;
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- opener,
- "window.domAutomationController.send(!!window.open('', '" + name + "'));",
- &success));
- EXPECT_TRUE(success);
- Shell* new_shell = new_shell_observer.GetShell();
- return new_shell;
-}
-
} // anonymous namespace
class RenderFrameHostManagerTest : public ContentBrowserTest {
@@ -578,7 +565,9 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
EXPECT_TRUE(orig_site_instance.get() != NULL);
// Open a popup using window.open with a 'foo' window.name.
- Shell* new_shell = OpenPopup(shell()->web_contents(), "foo");
+ Shell* new_shell =
+ OpenPopup(shell()->web_contents(), GURL(url::kAboutBlankURL), "foo");
+ EXPECT_TRUE(new_shell);
// The window.name for the new popup should be "foo".
std::string name;
@@ -602,7 +591,9 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
EXPECT_EQ("foo", name);
// Open another popup from the 'foo' popup and navigate it cross-site.
- Shell* new_shell2 = OpenPopup(new_shell->web_contents(), "bar");
+ Shell* new_shell2 =
+ OpenPopup(new_shell->web_contents(), GURL(url::kAboutBlankURL), "bar");
+ EXPECT_TRUE(new_shell2);
GURL bar_url(embedded_test_server()->GetURL("bar.com", "/title3.html"));
EXPECT_TRUE(NavigateToURL(new_shell2, bar_url));
@@ -1900,7 +1891,9 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
EXPECT_TRUE(orig_site_instance);
// Open a popup and navigate it cross-site.
- Shell* new_shell = OpenPopup(shell()->web_contents(), "foo");
+ Shell* new_shell =
+ OpenPopup(shell()->web_contents(), GURL(url::kAboutBlankURL), "foo");
+ EXPECT_TRUE(new_shell);
FrameTreeNode* popup_root =
static_cast<WebContentsImpl*>(new_shell->web_contents())
->GetFrameTree()
diff --git a/content/browser/renderer_host/render_view_host_delegate.h b/content/browser/renderer_host/render_view_host_delegate.h
index 9c1edce..ad1029c 100644
--- a/content/browser/renderer_host/render_view_host_delegate.h
+++ b/content/browser/renderer_host/render_view_host_delegate.h
@@ -196,9 +196,9 @@ class CONTENT_EXPORT RenderViewHostDelegate {
virtual void LostMouseLock() {}
// The page is trying to open a new page (e.g. a popup window). The window
- // should be created associated with the given |route_id| in process
- // |render_process_id|, but it should not be shown yet. That should happen in
- // response to ShowCreatedWindow.
+ // should be created associated with the given |route_id| in the process of
+ // |source_site_instance|, but it should not be shown yet. That
+ // should happen in response to ShowCreatedWindow.
// |params.window_container_type| describes the type of RenderViewHost
// container that is requested -- in particular, the window.open call may
// have specified 'background' and 'persistent' in the feature string.
@@ -208,8 +208,12 @@ class CONTENT_EXPORT RenderViewHostDelegate {
//
// Note: this is not called "CreateWindow" because that will clash with
// the Windows function which is actually a #define.
+ //
+ // TODO(alexmos): This should be moved to RenderFrameHostDelegate, and the
+ // corresponding IPC message should be sent by the RenderFrame creating the
+ // new window.
virtual void CreateNewWindow(
- int render_process_id,
+ SiteInstance* source_site_instance,
int route_id,
int main_frame_route_id,
const ViewHostMsg_CreateWindow_Params& params,
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index 2bc572f0..990f960 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -984,9 +984,8 @@ void RenderViewHostImpl::CreateNewWindow(
GetProcess()->FilterURL(false, &validated_params.opener_url);
GetProcess()->FilterURL(true, &validated_params.opener_security_origin);
- delegate_->CreateNewWindow(
- GetProcess()->GetID(), route_id, main_frame_route_id, validated_params,
- session_storage_namespace);
+ delegate_->CreateNewWindow(GetSiteInstance(), route_id, main_frame_route_id,
+ validated_params, session_storage_namespace);
}
void RenderViewHostImpl::CreateNewWidget(int route_id,
@@ -1002,10 +1001,8 @@ void RenderViewHostImpl::OnShowView(int route_id,
WindowOpenDisposition disposition,
const gfx::Rect& initial_rect,
bool user_gesture) {
- if (is_active_) {
- delegate_->ShowCreatedWindow(
- route_id, disposition, initial_rect, user_gesture);
- }
+ delegate_->ShowCreatedWindow(route_id, disposition, initial_rect,
+ user_gesture);
Send(new ViewMsg_Move_ACK(route_id));
}
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index c5514f6..7f1f029 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -2715,4 +2715,69 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, RFPHDestruction) {
DepictFrameTree(root));
}
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OpenPopupWithRemoteParent) {
+ GURL main_url(
+ embedded_test_server()->GetURL("a.com", "/site_per_process_main.html"));
+ NavigateToURL(shell(), main_url);
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // Navigate first child cross-site.
+ GURL frame_url(embedded_test_server()->GetURL("b.com", "/title1.html"));
+ NavigateFrameToURL(root->child_at(0), frame_url);
+
+ // Open a popup from the first child.
+ Shell* new_shell = OpenPopup(root->child_at(0)->current_frame_host(),
+ GURL(url::kAboutBlankURL), "");
+ EXPECT_TRUE(new_shell);
+
+ // Check that the popup's opener is correct on both the browser and renderer
+ // sides.
+ FrameTreeNode* popup_root =
+ static_cast<WebContentsImpl*>(new_shell->web_contents())
+ ->GetFrameTree()
+ ->root();
+ EXPECT_EQ(root->child_at(0), popup_root->opener());
+
+ std::string opener_url;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ popup_root->current_frame_host(),
+ "window.domAutomationController.send(window.opener.location.href);",
+ &opener_url));
+ EXPECT_EQ(frame_url.spec(), opener_url);
+
+ // Now try the same with a cross-site popup and make sure it ends up in a new
+ // process and with a correct opener.
+ GURL popup_url(embedded_test_server()->GetURL("c.com", "/title2.html"));
+ Shell* cross_site_popup =
+ OpenPopup(root->child_at(0)->current_frame_host(), popup_url, "");
+ EXPECT_TRUE(cross_site_popup);
+
+ FrameTreeNode* cross_site_popup_root =
+ static_cast<WebContentsImpl*>(cross_site_popup->web_contents())
+ ->GetFrameTree()
+ ->root();
+ EXPECT_EQ(cross_site_popup_root->current_url(), popup_url);
+
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
+ cross_site_popup->web_contents()->GetSiteInstance());
+ EXPECT_NE(root->child_at(0)->current_frame_host()->GetSiteInstance(),
+ cross_site_popup->web_contents()->GetSiteInstance());
+
+ EXPECT_EQ(root->child_at(0), cross_site_popup_root->opener());
+
+ // Ensure the popup's window.opener points to the right subframe. Note that
+ // we can't check the opener's location as above since it's cross-origin.
+ bool success = false;
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(
+ cross_site_popup_root->current_frame_host(),
+ "window.domAutomationController.send("
+ " window.opener === window.opener.top.frames[0]);",
+ &success));
+ EXPECT_TRUE(success);
+}
+
} // namespace content
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 028eada..38903a01 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -172,6 +172,16 @@ bool CollectSites(BrowserContext* context,
return true;
}
+bool FindMatchingProcess(int render_process_id,
+ bool* did_match_process,
+ FrameTreeNode* node) {
+ if (node->current_frame_host()->GetProcess()->GetID() == render_process_id) {
+ *did_match_process = true;
+ return false;
+ }
+ return true;
+}
+
bool ForEachFrameInternal(
const base::Callback<void(RenderFrameHost*)>& on_frame,
FrameTreeNode* node) {
@@ -1607,7 +1617,7 @@ void WebContentsImpl::LostMouseLock() {
}
void WebContentsImpl::CreateNewWindow(
- int render_process_id,
+ SiteInstance* source_site_instance,
int route_id,
int main_frame_route_id,
const ViewHostMsg_CreateWindow_Params& params,
@@ -1632,15 +1642,19 @@ void WebContentsImpl::CreateNewWindow(
DCHECK(!params.opener_suppressed || route_id == MSG_ROUTING_NONE);
scoped_refptr<SiteInstance> site_instance =
- params.opener_suppressed && !is_guest ?
- SiteInstance::CreateForURL(GetBrowserContext(), params.target_url) :
- GetSiteInstance();
-
- // A message to create a new window can only come from the active process for
- // this WebContentsImpl instance. If any other process sends the request,
- // it is invalid and the process must be terminated.
- if (GetRenderProcessHost()->GetID() != render_process_id) {
- RenderProcessHost* rph = RenderProcessHost::FromID(render_process_id);
+ params.opener_suppressed && !is_guest
+ ? SiteInstance::CreateForURL(GetBrowserContext(), params.target_url)
+ : source_site_instance;
+
+ // A message to create a new window can only come from a process for a frame
+ // in this WebContents' FrameTree. If any other process sends the request, it
+ // is invalid and the process must be terminated.
+ int render_process_id = source_site_instance->GetProcess()->GetID();
+ bool did_match_process = false;
+ frame_tree_.ForEach(
+ base::Bind(&FindMatchingProcess, render_process_id, &did_match_process));
+ if (!did_match_process) {
+ RenderProcessHost* rph = source_site_instance->GetProcess();
base::ProcessHandle process_handle = rph->GetHandle();
if (process_handle != base::kNullProcessHandle) {
RecordAction(
@@ -1692,7 +1706,7 @@ void WebContentsImpl::CreateNewWindow(
create_params.routing_id = route_id;
create_params.main_frame_routing_id = main_frame_route_id;
create_params.main_frame_name = params.frame_name;
- create_params.opener_render_process_id = GetRenderProcessHost()->GetID();
+ create_params.opener_render_process_id = render_process_id;
create_params.opener_render_frame_id = params.opener_render_frame_id;
create_params.opener_suppressed = params.opener_suppressed;
if (params.disposition == NEW_BACKGROUND_TAB)
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index a3b6d30..e686c44 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -480,7 +480,7 @@ class CONTENT_EXPORT WebContentsImpl
bool last_unlocked_by_target) override;
void LostMouseLock() override;
void CreateNewWindow(
- int render_process_id,
+ SiteInstance* source_site_instance,
int route_id,
int main_frame_route_id,
const ViewHostMsg_CreateWindow_Params& params,
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 2310257..8e6c405 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -110,8 +110,6 @@
'test/browser_side_navigation_test_utils.h',
'test/content_browser_sanity_checker.cc',
'test/content_browser_sanity_checker.h',
- 'test/content_browser_test_utils_internal.cc',
- 'test/content_browser_test_utils_internal.h',
'test/content_test_suite.cc',
'test/content_test_suite.h',
'test/fake_compositor_dependencies.cc',
@@ -1331,6 +1329,8 @@
'public/test/content_browser_test_utils.cc',
'public/test/content_browser_test_utils.h',
'public/test/content_browser_test_utils_mac.mm',
+ 'test/content_browser_test_utils_internal.cc',
+ 'test/content_browser_test_utils_internal.h',
'test/content_test_launcher.cc',
],
'include_dirs': [
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index 001ceea..bbae7f8 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -540,8 +540,6 @@ void SimulateKeyPressWithCode(WebContents* web_contents,
ASSERT_EQ(modifiers, 0);
}
-namespace internal {
-
ToRenderFrameHost::ToRenderFrameHost(WebContents* web_contents)
: render_frame_host_(web_contents->GetMainFrame()) {
}
@@ -554,16 +552,14 @@ ToRenderFrameHost::ToRenderFrameHost(RenderFrameHost* render_frame_host)
: render_frame_host_(render_frame_host) {
}
-} // namespace internal
-
-bool ExecuteScript(const internal::ToRenderFrameHost& adapter,
+bool ExecuteScript(const ToRenderFrameHost& adapter,
const std::string& script) {
std::string new_script =
script + ";window.domAutomationController.send(0);";
return ExecuteScriptHelper(adapter.render_frame_host(), new_script, NULL);
}
-bool ExecuteScriptAndExtractInt(const internal::ToRenderFrameHost& adapter,
+bool ExecuteScriptAndExtractInt(const ToRenderFrameHost& adapter,
const std::string& script, int* result) {
DCHECK(result);
scoped_ptr<base::Value> value;
@@ -575,7 +571,7 @@ bool ExecuteScriptAndExtractInt(const internal::ToRenderFrameHost& adapter,
return value->GetAsInteger(result);
}
-bool ExecuteScriptAndExtractBool(const internal::ToRenderFrameHost& adapter,
+bool ExecuteScriptAndExtractBool(const ToRenderFrameHost& adapter,
const std::string& script, bool* result) {
DCHECK(result);
scoped_ptr<base::Value> value;
@@ -587,7 +583,7 @@ bool ExecuteScriptAndExtractBool(const internal::ToRenderFrameHost& adapter,
return value->GetAsBoolean(result);
}
-bool ExecuteScriptAndExtractString(const internal::ToRenderFrameHost& adapter,
+bool ExecuteScriptAndExtractString(const ToRenderFrameHost& adapter,
const std::string& script,
std::string* result) {
DCHECK(result);
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h
index 7de4fd7..72bbd02 100644
--- a/content/public/test/browser_test_utils.h
+++ b/content/public/test/browser_test_utils.h
@@ -157,7 +157,6 @@ void SimulateKeyPressWithCode(WebContents* web_contents,
bool alt,
bool command);
-namespace internal {
// Allow ExecuteScript* methods to target either a WebContents or a
// RenderFrameHost. Targetting a WebContents means executing the script in the
// RenderFrameHost returned by WebContents::GetMainFrame(), which is the
@@ -173,26 +172,25 @@ class ToRenderFrameHost {
private:
RenderFrameHost* render_frame_host_;
};
-} // namespace internal
// Executes the passed |script| in the specified frame. The |script| should not
// invoke domAutomationController.send(); otherwise, your test will hang or be
// flaky. If you want to extract a result, use one of the below functions.
// Returns true on success.
-bool ExecuteScript(const internal::ToRenderFrameHost& adapter,
+bool ExecuteScript(const ToRenderFrameHost& adapter,
const std::string& script) WARN_UNUSED_RESULT;
// The following methods executes the passed |script| in the specified frame and
// sets |result| to the value passed to "window.domAutomationController.send" by
// the executed script. They return true on success, false if the script
// execution failed or did not evaluate to the expected type.
-bool ExecuteScriptAndExtractInt(const internal::ToRenderFrameHost& adapter,
+bool ExecuteScriptAndExtractInt(const ToRenderFrameHost& adapter,
const std::string& script,
int* result) WARN_UNUSED_RESULT;
-bool ExecuteScriptAndExtractBool(const internal::ToRenderFrameHost& adapter,
+bool ExecuteScriptAndExtractBool(const ToRenderFrameHost& adapter,
const std::string& script,
bool* result) WARN_UNUSED_RESULT;
-bool ExecuteScriptAndExtractString(const internal::ToRenderFrameHost& adapter,
+bool ExecuteScriptAndExtractString(const ToRenderFrameHost& adapter,
const std::string& script,
std::string* result) WARN_UNUSED_RESULT;
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 8376f0d..4a10b6d 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -189,6 +189,8 @@ source_set("browsertest_support") {
"../public/test/content_browser_test_utils.cc",
"../public/test/content_browser_test_utils.h",
"../public/test/content_browser_test_utils_mac.mm",
+ "content_browser_test_utils_internal.cc",
+ "content_browser_test_utils_internal.h",
"content_test_launcher.cc",
]
diff --git a/content/test/content_browser_test_utils_internal.cc b/content/test/content_browser_test_utils_internal.cc
index 9097a89..ea1d17e 100644
--- a/content/test/content_browser_test_utils_internal.cc
+++ b/content/test/content_browser_test_utils_internal.cc
@@ -13,6 +13,9 @@
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/render_frame_proxy_host.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
#include "content/test/test_frame_navigation_observer.h"
#include "url/gurl.h"
@@ -219,4 +222,22 @@ std::string FrameTreeVisualizer::GetName(SiteInstance* site_instance) {
return base::StringPrintf("Z%d", static_cast<int>(index - 25));
}
+Shell* OpenPopup(const ToRenderFrameHost& opener,
+ const GURL& url,
+ const std::string& name) {
+ ShellAddedObserver new_shell_observer;
+ bool did_create_popup = false;
+ bool did_execute_script = ExecuteScriptAndExtractBool(
+ opener,
+ "window.domAutomationController.send("
+ " !!window.open('" + url.spec() + "', '" + name + "'));",
+ &did_create_popup);
+ if (!did_execute_script || !did_create_popup)
+ return nullptr;
+
+ Shell* new_shell = new_shell_observer.GetShell();
+ WaitForLoadStop(new_shell->web_contents());
+ return new_shell;
+}
+
} // namespace content
diff --git a/content/test/content_browser_test_utils_internal.h b/content/test/content_browser_test_utils_internal.h
index 4486d14..05544b8 100644
--- a/content/test/content_browser_test_utils_internal.h
+++ b/content/test/content_browser_test_utils_internal.h
@@ -20,7 +20,9 @@ class GURL;
namespace content {
class FrameTreeNode;
+class Shell;
class SiteInstance;
+class ToRenderFrameHost;
// Navigates the frame represented by |node| to |url|, blocking until the
// navigation finishes.
@@ -65,6 +67,15 @@ class FrameTreeVisualizer {
DISALLOW_COPY_AND_ASSIGN(FrameTreeVisualizer);
};
+// Uses window.open to open a popup from the frame |opener| with the specified
+// |url| and |name|. Waits for the navigation to |url| to finish and then
+// returns the new popup's Shell. Note that since this navigation to |url| is
+// renderer-initiated, it won't cause a process swap unless used in
+// --site-per-process mode.
+Shell* OpenPopup(const ToRenderFrameHost& opener,
+ const GURL& url,
+ const std::string& name);
+
} // namespace content
#endif // CONTENT_TEST_CONTENT_BROWSER_TEST_UTILS_INTERNAL_H_
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc
index 9bf027f..27d5404 100644
--- a/content/test/test_web_contents.cc
+++ b/content/test/test_web_contents.cc
@@ -278,7 +278,7 @@ void TestWebContents::TestDidFailLoadWithError(
}
void TestWebContents::CreateNewWindow(
- int render_process_id,
+ SiteInstance* source_site_instance,
int route_id,
int main_frame_route_id,
const ViewHostMsg_CreateWindow_Params& params,
diff --git a/content/test/test_web_contents.h b/content/test/test_web_contents.h
index ffc7619..3e45d8a 100644
--- a/content/test/test_web_contents.h
+++ b/content/test/test_web_contents.h
@@ -116,7 +116,7 @@ class TestWebContents : public WebContentsImpl, public WebContentsTester {
private:
// WebContentsImpl overrides
void CreateNewWindow(
- int render_process_id,
+ SiteInstance* source_site_instance,
int route_id,
int main_frame_route_id,
const ViewHostMsg_CreateWindow_Params& params,