Commit 4128efcc authored by Luca Versari's avatar Luca Versari Committed by Commit Bot

headless: Implement HeadlessWebContentImpl::Delegate::OpenURLFromTab

OpenURLFromTab in headless used the default implementation, that does
nothing. This caused a couple of issues when the rendered asked the
browser to create new content. The most clear effect of this was that
setting window.location via JavaScript from the about:blank page had
no effect, but it also caused issues with other renderer-initiated but
browser-controlled navigations.


R=eseckler@chromium.org

Bug: 739969
Change-Id: I4c1080c2f41d5701b44b8c7e87d8a697c408e539
Reviewed-on: https://chromium-review.googlesource.com/600218Reviewed-by: default avatarEric Seckler <eseckler@chromium.org>
Commit-Queue: Luca Versari <veluca@google.com>
Cr-Commit-Position: refs/heads/master@{#492010}
parent 31a33e1b
...@@ -125,6 +125,63 @@ class HeadlessWebContentsImpl::Delegate : public content::WebContentsDelegate { ...@@ -125,6 +125,63 @@ class HeadlessWebContentsImpl::Delegate : public content::WebContentsDelegate {
headless_contents->SetBounds(rect); headless_contents->SetBounds(rect);
} }
content::WebContents* OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) override {
DCHECK_EQ(source, headless_web_contents_->web_contents());
content::WebContents* target = nullptr;
switch (params.disposition) {
case WindowOpenDisposition::CURRENT_TAB:
target = source;
break;
case WindowOpenDisposition::NEW_POPUP:
case WindowOpenDisposition::NEW_WINDOW:
case WindowOpenDisposition::NEW_BACKGROUND_TAB:
case WindowOpenDisposition::NEW_FOREGROUND_TAB: {
HeadlessWebContentsImpl* child_contents = HeadlessWebContentsImpl::From(
headless_web_contents_->browser_context()
->CreateWebContentsBuilder()
.SetAllowTabSockets(
!!headless_web_contents_->GetHeadlessTabSocket())
.SetWindowSize(source->GetContainerBounds().size())
.Build());
headless_web_contents_->browser_context()->NotifyChildContentsCreated(
headless_web_contents_, child_contents);
target = child_contents->web_contents();
break;
}
// TODO(veluca): add support for other disposition types.
case WindowOpenDisposition::SINGLETON_TAB:
case WindowOpenDisposition::OFF_THE_RECORD:
case WindowOpenDisposition::SAVE_TO_DISK:
case WindowOpenDisposition::IGNORE_ACTION:
default:
return nullptr;
}
content::NavigationController::LoadURLParams load_url_params(params.url);
load_url_params.source_site_instance = params.source_site_instance;
load_url_params.transition_type = params.transition;
load_url_params.frame_tree_node_id = params.frame_tree_node_id;
load_url_params.referrer = params.referrer;
load_url_params.redirect_chain = params.redirect_chain;
load_url_params.extra_headers = params.extra_headers;
load_url_params.is_renderer_initiated = params.is_renderer_initiated;
load_url_params.should_replace_current_entry =
params.should_replace_current_entry;
if (params.uses_post) {
load_url_params.load_type =
content::NavigationController::LOAD_TYPE_HTTP_POST;
load_url_params.post_data = params.post_data;
}
target->GetController().LoadURLWithParams(load_url_params);
return target;
}
private: private:
HeadlessBrowserImpl* browser() { return headless_web_contents_->browser(); } HeadlessBrowserImpl* browser() { return headless_web_contents_->browser(); }
......
...@@ -864,4 +864,51 @@ class HeadlessWebContentsRequestStorageQuotaTest ...@@ -864,4 +864,51 @@ class HeadlessWebContentsRequestStorageQuotaTest
HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessWebContentsRequestStorageQuotaTest); HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessWebContentsRequestStorageQuotaTest);
IN_PROC_BROWSER_TEST_F(HeadlessWebContentsTest, BrowserTabChangeContent) {
EXPECT_TRUE(embedded_test_server()->Start());
HeadlessBrowserContext* browser_context =
browser()->CreateBrowserContextBuilder().Build();
HeadlessWebContents* web_contents =
browser_context->CreateWebContentsBuilder().Build();
EXPECT_TRUE(WaitForLoad(web_contents));
std::string script = "window.location = '" +
embedded_test_server()->GetURL("/hello.html").spec() +
"';";
EXPECT_FALSE(EvaluateScript(web_contents, script)->HasExceptionDetails());
// This will time out if the previous script did not work.
EXPECT_TRUE(WaitForLoad(web_contents));
}
IN_PROC_BROWSER_TEST_F(HeadlessWebContentsTest, BrowserOpenInTab) {
EXPECT_TRUE(embedded_test_server()->Start());
HeadlessBrowserContext* browser_context =
browser()->CreateBrowserContextBuilder().Build();
MockHeadlessBrowserContextObserver observer;
browser_context->AddObserver(&observer);
EXPECT_CHILD_CONTENTS_CREATED(observer);
HeadlessWebContents* web_contents =
browser_context->CreateWebContentsBuilder()
.SetInitialURL(embedded_test_server()->GetURL("/link.html"))
.Build();
EXPECT_TRUE(WaitForLoad(web_contents));
EXPECT_EQ(1u, browser_context->GetAllWebContents().size());
// Simulates a middle-button click on a link to ensure that the
// link is opened in a new tab by the browser and not by the renderer.
std::string script =
"var event = new MouseEvent('click', {'button': 1});"
"document.getElementsByTagName('a')[0].dispatchEvent(event);";
EXPECT_FALSE(EvaluateScript(web_contents, script)->HasExceptionDetails());
// Check that we have a new tab.
EXPECT_EQ(2u, browser_context->GetAllWebContents().size());
browser_context->RemoveObserver(&observer);
}
} // namespace headless } // namespace headless
<a href="hello.html">Click me!</a>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment