Commit 029bd2f8 authored by Pavel Feldman's avatar Pavel Feldman Committed by Commit Bot

DevTools: introduce Page.navigate(frameId).

Change-Id: I8e7854752054f0e4ac1c88fe9b9ec5e9e9547876
Reviewed-on: https://chromium-review.googlesource.com/885422
Commit-Queue: Pavel Feldman <pfeldman@chromium.org>
Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#532140}
parent 617c1708
...@@ -2119,73 +2119,6 @@ class SitePerProcessDevToolsProtocolTest : public DevToolsProtocolTest { ...@@ -2119,73 +2119,6 @@ class SitePerProcessDevToolsProtocolTest : public DevToolsProtocolTest {
} }
}; };
IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsProtocolTest, TargetNoDiscovery) {
std::string temp;
std::string target_id;
std::unique_ptr<base::DictionaryValue> command_params;
std::unique_ptr<base::DictionaryValue> params;
GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
NavigateToURLBlockUntilNavigationsComplete(shell(), main_url, 1);
// 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();
// Load cross-site page into iframe.
GURL::Replacements replace_host;
GURL cross_site_url(embedded_test_server()->GetURL("/title1.html"));
replace_host.SetHostStr("foo.com");
cross_site_url = cross_site_url.ReplaceComponents(replace_host);
NavigateFrameToURL(root->child_at(0), cross_site_url);
// Enable auto-attach.
Attach();
command_params.reset(new base::DictionaryValue());
command_params->SetBoolean("autoAttach", true);
command_params->SetBoolean("waitForDebuggerOnStart", false);
SendCommand("Target.setAutoAttach", std::move(command_params), true);
EXPECT_TRUE(notifications_.empty());
command_params.reset(new base::DictionaryValue());
command_params->SetBoolean("value", true);
SendCommand("Target.setAttachToFrames", std::move(command_params), false);
params = WaitForNotification("Target.attachedToTarget", true);
std::string session_id;
EXPECT_TRUE(params->GetString("sessionId", &session_id));
EXPECT_TRUE(params->GetString("targetInfo.targetId", &target_id));
EXPECT_TRUE(params->GetString("targetInfo.type", &temp));
EXPECT_EQ("iframe", temp);
// Load same-site page into iframe.
FrameTreeNode* child = root->child_at(0);
GURL http_url(embedded_test_server()->GetURL("/title1.html"));
NavigateFrameToURL(child, http_url);
params = WaitForNotification("Target.detachedFromTarget", true);
EXPECT_TRUE(params->GetString("targetId", &temp));
EXPECT_EQ(target_id, temp);
EXPECT_TRUE(params->GetString("sessionId", &temp));
EXPECT_EQ(session_id, temp);
// Navigate back to cross-site iframe.
NavigateFrameToURL(root->child_at(0), cross_site_url);
params = WaitForNotification("Target.attachedToTarget", true);
EXPECT_TRUE(params->GetString("sessionId", &session_id));
EXPECT_TRUE(params->GetString("targetInfo.targetId", &target_id));
EXPECT_TRUE(params->GetString("targetInfo.type", &temp));
EXPECT_EQ("iframe", temp);
// Disable auto-attach.
command_params.reset(new base::DictionaryValue());
command_params->SetBoolean("autoAttach", false);
command_params->SetBoolean("waitForDebuggerOnStart", false);
SendCommand("Target.setAutoAttach", std::move(command_params), false);
params = WaitForNotification("Target.detachedFromTarget", true);
EXPECT_TRUE(params->GetString("targetId", &temp));
EXPECT_EQ(target_id, temp);
EXPECT_TRUE(params->GetString("sessionId", &temp));
EXPECT_EQ(session_id, temp);
}
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, SetAndGetCookies) { IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, SetAndGetCookies) {
ASSERT_TRUE(embedded_test_server()->Start()); ASSERT_TRUE(embedded_test_server()->Start());
GURL test_url = embedded_test_server()->GetURL("/title1.html"); GURL test_url = embedded_test_server()->GetURL("/title1.html");
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "content/browser/devtools/protocol/devtools_download_manager_helper.h" #include "content/browser/devtools/protocol/devtools_download_manager_helper.h"
#include "content/browser/devtools/protocol/emulation_handler.h" #include "content/browser/devtools/protocol/emulation_handler.h"
#include "content/browser/frame_host/navigation_request.h" #include "content/browser/frame_host/navigation_request.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/manifest/manifest_manager_host.h" #include "content/browser/manifest/manifest_manager_host.h"
#include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/browser/renderer_host/render_widget_host_view_base.h"
...@@ -286,6 +287,7 @@ Response PageHandler::Disable() { ...@@ -286,6 +287,7 @@ Response PageHandler::Disable() {
} }
download_manager_delegate_ = nullptr; download_manager_delegate_ = nullptr;
navigate_callbacks_.clear();
return Response::FallThrough(); return Response::FallThrough();
} }
...@@ -323,6 +325,7 @@ Response PageHandler::Reload(Maybe<bool> bypassCache, ...@@ -323,6 +325,7 @@ Response PageHandler::Reload(Maybe<bool> bypassCache,
void PageHandler::Navigate(const std::string& url, void PageHandler::Navigate(const std::string& url,
Maybe<std::string> referrer, Maybe<std::string> referrer,
Maybe<std::string> maybe_transition_type, Maybe<std::string> maybe_transition_type,
Maybe<std::string> frame_id,
std::unique_ptr<NavigateCallback> callback) { std::unique_ptr<NavigateCallback> callback) {
GURL gurl(url); GURL gurl(url);
if (!gurl.is_valid()) { if (!gurl.is_valid()) {
...@@ -330,8 +333,7 @@ void PageHandler::Navigate(const std::string& url, ...@@ -330,8 +333,7 @@ void PageHandler::Navigate(const std::string& url,
return; return;
} }
WebContentsImpl* web_contents = GetWebContents(); if (!host_) {
if (!web_contents) {
callback->sendFailure(Response::InternalError()); callback->sendFailure(Response::InternalError());
return; return;
} }
...@@ -364,43 +366,64 @@ void PageHandler::Navigate(const std::string& url, ...@@ -364,43 +366,64 @@ void PageHandler::Navigate(const std::string& url,
else else
type = ui::PAGE_TRANSITION_TYPED; type = ui::PAGE_TRANSITION_TYPED;
web_contents->GetController().LoadURL( FrameTreeNode* frame_tree_node = nullptr;
gurl, std::string out_frame_id = frame_id.fromMaybe(
Referrer(GURL(referrer.fromMaybe("")), blink::kWebReferrerPolicyDefault), host_->frame_tree_node()->devtools_frame_token().ToString());
type, std::string()); FrameTreeNode* root = host_->frame_tree_node();
std::string frame_id = if (root->devtools_frame_token().ToString() == out_frame_id) {
web_contents->GetMainFrame()->GetDevToolsFrameToken().ToString(); frame_tree_node = root;
if (navigate_callback_) { } else {
for (FrameTreeNode* node : root->frame_tree()->SubtreeNodes(root)) {
if (node->devtools_frame_token().ToString() == out_frame_id) {
frame_tree_node = node;
break;
}
}
}
if (!frame_tree_node) {
callback->sendFailure(Response::Error("No frame with given id found"));
return;
}
NavigationController::LoadURLParams params(gurl);
params.referrer =
Referrer(GURL(referrer.fromMaybe("")), blink::kWebReferrerPolicyDefault);
params.transition_type = type;
params.frame_tree_node_id = frame_tree_node->frame_tree_node_id();
frame_tree_node->navigator()->GetController()->LoadURLWithParams(params);
base::UnguessableToken frame_token = frame_tree_node->devtools_frame_token();
auto navigate_callback = navigate_callbacks_.find(frame_token);
if (navigate_callback != navigate_callbacks_.end()) {
std::string error_string = net::ErrorToString(net::ERR_ABORTED); std::string error_string = net::ErrorToString(net::ERR_ABORTED);
navigate_callback_->sendSuccess(frame_id, Maybe<std::string>(), navigate_callback->second->sendSuccess(out_frame_id, Maybe<std::string>(),
Maybe<std::string>(error_string)); Maybe<std::string>(error_string));
}
if (frame_tree_node->navigation_request()) {
navigate_callbacks_[frame_token] = std::move(callback);
} else {
callback->sendSuccess(out_frame_id, Maybe<std::string>(),
Maybe<std::string>());
} }
if (web_contents->GetMainFrame()->frame_tree_node()->navigation_request())
navigate_callback_ = std::move(callback);
else
callback->sendSuccess(frame_id, Maybe<std::string>(), Maybe<std::string>());
} }
void PageHandler::NavigationReset(NavigationRequest* navigation_request) { void PageHandler::NavigationReset(NavigationRequest* navigation_request) {
if (!navigate_callback_) auto navigate_callback = navigate_callbacks_.find(
navigation_request->frame_tree_node()->devtools_frame_token());
if (navigate_callback == navigate_callbacks_.end())
return; return;
WebContentsImpl* web_contents = GetWebContents();
if (!web_contents) {
navigate_callback_->sendFailure(Response::InternalError());
return;
}
std::string frame_id = std::string frame_id =
web_contents->GetMainFrame()->GetDevToolsFrameToken().ToString(); navigation_request->frame_tree_node()->devtools_frame_token().ToString();
bool success = navigation_request->net_error() != net::OK; bool success = navigation_request->net_error() != net::OK;
std::string error_string = std::string error_string =
net::ErrorToString(navigation_request->net_error()); net::ErrorToString(navigation_request->net_error());
navigate_callback_->sendSuccess( navigate_callback->second->sendSuccess(
frame_id, frame_id,
Maybe<std::string>( Maybe<std::string>(
navigation_request->devtools_navigation_token().ToString()), navigation_request->devtools_navigation_token().ToString()),
success ? Maybe<std::string>(error_string) : Maybe<std::string>()); success ? Maybe<std::string>(error_string) : Maybe<std::string>());
navigate_callback_.reset(); navigate_callbacks_.erase(navigate_callback);
} }
static const char* TransitionTypeName(ui::PageTransition type) { static const char* TransitionTypeName(ui::PageTransition type) {
......
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
class SkBitmap; class SkBitmap;
namespace base {
class UnguessableToken;
}
namespace gfx { namespace gfx {
class Image; class Image;
} // namespace gfx } // namespace gfx
...@@ -90,6 +94,7 @@ class PageHandler : public DevToolsDomainHandler, ...@@ -90,6 +94,7 @@ class PageHandler : public DevToolsDomainHandler,
void Navigate(const std::string& url, void Navigate(const std::string& url,
Maybe<std::string> referrer, Maybe<std::string> referrer,
Maybe<std::string> transition_type, Maybe<std::string> transition_type,
Maybe<std::string> frame_id,
std::unique_ptr<NavigateCallback> callback) override; std::unique_ptr<NavigateCallback> callback) override;
Response StopLoading() override; Response StopLoading() override;
...@@ -194,7 +199,8 @@ class PageHandler : public DevToolsDomainHandler, ...@@ -194,7 +199,8 @@ class PageHandler : public DevToolsDomainHandler,
NotificationRegistrar registrar_; NotificationRegistrar registrar_;
JavaScriptDialogCallback pending_dialog_; JavaScriptDialogCallback pending_dialog_;
scoped_refptr<DevToolsDownloadManagerDelegate> download_manager_delegate_; scoped_refptr<DevToolsDownloadManagerDelegate> download_manager_delegate_;
std::unique_ptr<NavigateCallback> navigate_callback_; base::flat_map<base::UnguessableToken, std::unique_ptr<NavigateCallback>>
navigate_callbacks_;
base::WeakPtrFactory<PageHandler> weak_factory_; base::WeakPtrFactory<PageHandler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PageHandler); DISALLOW_COPY_AND_ASSIGN(PageHandler);
......
...@@ -170,16 +170,26 @@ void RenderFrameDevToolsAgentHost::AddAllAgentHosts( ...@@ -170,16 +170,26 @@ void RenderFrameDevToolsAgentHost::AddAllAgentHosts(
// static // static
void RenderFrameDevToolsAgentHost::OnResetNavigationRequest( void RenderFrameDevToolsAgentHost::OnResetNavigationRequest(
NavigationRequest* navigation_request) { NavigationRequest* navigation_request) {
RenderFrameDevToolsAgentHost* agent_host = // Communicate network error to own agent host only.
FindAgentHost(navigation_request->frame_tree_node());
if (!agent_host)
return;
if (navigation_request->net_error() != net::OK) { if (navigation_request->net_error() != net::OK) {
for (auto* network : protocol::NetworkHandler::ForAgentHost(agent_host)) RenderFrameDevToolsAgentHost* agent_host =
network->NavigationFailed(navigation_request); FindAgentHost(navigation_request->frame_tree_node());
if (agent_host) {
for (auto* network : protocol::NetworkHandler::ForAgentHost(agent_host))
network->NavigationFailed(navigation_request);
}
}
// Traverse frame chain all the way to the top and report to all
// page handlers that the navigation completed.
for (FrameTreeNode* node = navigation_request->frame_tree_node(); node;
node = node->parent()) {
RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(node);
if (!agent_host)
continue;
for (auto* page : protocol::PageHandler::ForAgentHost(agent_host))
page->NavigationReset(navigation_request);
} }
for (auto* page : protocol::PageHandler::ForAgentHost(agent_host))
page->NavigationReset(navigation_request);
} }
// static // static
......
<html>
<title>site_per_process_main</title>
<head></head>
<body>
<iframe id="test"></iframe>
<iframe id="child-2" src="http://devtools.oopif.test:8000/inspector-protocol/resources/iframe.html"></iframe>
</body>
</html>
Tests oopif discovery.
Enabling auto-discovery...
Got auto-attached.
Navigating to in-process iframe...
Session id should match: true
Target id should match: true
Navigating back to out-of-process iframe...
Target ids should match: true
Session id should match: true
Target id should match: true
(async function(testRunner) {
var {page, session, dp} = await testRunner.startBlank(`Tests oopif discovery.`);
await dp.Page.enable();
dp.Page.navigate({url: testRunner.url('../resources/site_per_process_main.html')});
await dp.Page.onceLoadEventFired();
testRunner.log('Enabling auto-discovery...');
await dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false});
dp.Target.setAttachToFrames({value: true});
let attachedEvent = (await dp.Target.onceAttachedToTarget()).params;
testRunner.log('Got auto-attached.');
let frameId = attachedEvent.targetInfo.targetId;
testRunner.log('Navigating to in-process iframe...');
let navigatePromise = dp.Page.navigate({frameId, url: testRunner.url('../resources/iframe.html')});
let detachedPromise = dp.Target.onceDetachedFromTarget();
await Promise.all([navigatePromise, detachedPromise]);
let detachedEvent = (await detachedPromise).params;
testRunner.log('Session id should match: ' + (attachedEvent.sessionId === detachedEvent.sessionId));
testRunner.log('Target id should match: ' + (attachedEvent.targetInfo.targetId === detachedEvent.targetId));
testRunner.log('Navigating back to out-of-process iframe...');
dp.Page.navigate({frameId, url: 'http://devtools.oopif.test:8000/inspector-protocol/resources/iframe.html'});
let attachedEvent2 = (await dp.Target.onceAttachedToTarget()).params;
testRunner.log('Target ids should match: ' + (attachedEvent.targetInfo.targetId === attachedEvent2.targetInfo.targetId));
dp.Target.setAutoAttach({autoAttach: false, waitForDebuggerOnStart: false});
let detachedEvent2 = (await dp.Target.onceDetachedFromTarget()).params;
testRunner.log('Session id should match: ' + (attachedEvent2.sessionId === detachedEvent2.sessionId));
testRunner.log('Target id should match: ' + (attachedEvent2.targetInfo.targetId === detachedEvent2.targetId));
testRunner.completeTest();
})
...@@ -9992,6 +9992,12 @@ ...@@ -9992,6 +9992,12 @@
"description": "Intended transition type.", "description": "Intended transition type.",
"optional": true, "optional": true,
"$ref": "TransitionType" "$ref": "TransitionType"
},
{
"name": "frameId",
"description": "Frame id to navigate, if not specified navigates the top frame.",
"optional": true,
"$ref": "FrameId"
} }
], ],
"returns": [ "returns": [
......
...@@ -4569,6 +4569,8 @@ domain Page ...@@ -4569,6 +4569,8 @@ domain Page
optional string referrer optional string referrer
# Intended transition type. # Intended transition type.
optional TransitionType transitionType optional TransitionType transitionType
# Frame id to navigate, if not specified navigates the top frame.
optional FrameId frameId
returns returns
# Frame id that has navigated (or failed to navigate) # Frame id that has navigated (or failed to navigate)
FrameId frameId FrameId frameId
......
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