Commit 4838b76a authored by Andrey Kosyakov's avatar Andrey Kosyakov Committed by Commit Bot

Add more checks for chrome.debugger extensions

Bug: 1113558, 1113565
Change-Id: I99f2e030f9a38f1ffd6b6adc760ba15e5d231f96
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2342277
Commit-Queue: Andrey Kosyakov <caseq@chromium.org>
Reviewed-by: default avatarSigurd Schneider <sigurds@chromium.org>
Reviewed-by: default avatarYang Guo <yangguo@chromium.org>
Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#799514}
parent 98718f3e
......@@ -381,4 +381,14 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDebuggerExtensionApiTest, Debugger) {
<< message_;
}
IN_PROC_BROWSER_TEST_F(SitePerProcessDebuggerExtensionApiTest,
NavigateSubframe) {
GURL url(embedded_test_server()->GetURL(
"a.com",
"/extensions/api_test/debugger_navigate_subframe/inspected_page.html"));
ASSERT_TRUE(
RunExtensionTestWithArg("debugger_navigate_subframe", url.spec().c_str()))
<< message_;
}
} // namespace extensions
// Copyright 2020 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.
const protocolVersion = '1.3';
const DETACHED_WHILE_HANDLING = 'Detached while handling command.';
chrome.test.getConfig(config => chrome.test.runTests([
async function testNavigateSubframe() {
const {openTab} = await import('/_test_resources/test_util/tabs_util.js');
const topURL = config.customArg;
const subframeURL = topURL.replace('http://a.com', 'http://b.com');
const tab = await openTab(topURL);
const debuggee = {tabId: tab.id};
await new Promise(resolve =>
chrome.debugger.attach(debuggee, protocolVersion, resolve));
chrome.debugger.sendCommand(debuggee, 'Page.enable', null);
const response = await new Promise(resolve =>
chrome.debugger.sendCommand(debuggee, 'Page.getFrameTree', resolve));
const subframeId = response.frameTree.childFrames[0].frame.id;
const expression = `
new Promise(resolve => {
const frame = document.body.firstElementChild;
frame.onload = resolve;
frame.src = '${subframeURL}';
})
`;
await new Promise(resolve =>
chrome.debugger.sendCommand(debuggee, 'Runtime.evaluate', {
expression,
awaitPromise: true
}, resolve));
chrome.test.assertNoLastError();
const result = await new Promise(resolve =>
chrome.debugger.sendCommand(debuggee, 'Page.navigate', {
frameId: subframeId,
url: 'devtools://devtools/bundled/inspector.html'
}, resolve));
chrome.test.assertLastError(DETACHED_WHILE_HANDLING);
chrome.test.succeed();
}
]));
<html>
<iframe></iframe>
</html>
\ No newline at end of file
{
"name": "Debugger API test for CDP-initiated navigation of subframes",
"version": "1.0",
"manifest_version": 2,
"background": {
"scripts": ["background.js"]
},
"permissions": [
"debugger"
]
}
......@@ -561,12 +561,23 @@ bool WillCreateURLLoaderFactory(
void OnNavigationRequestWillBeSent(
const NavigationRequest& navigation_request) {
// Note this intentionally deviates from the usual instrumentation signal
// logic and dispatches to all agents upwards from the frame, to make sure
// the security checks are properly applied even if no DevTools session is
// established for the navigated frame itself. This is because the page
// agent may navigate all of its subframes currently.
for (RenderFrameHostImpl* rfh =
navigation_request.frame_tree_node()->current_frame_host();
rfh; rfh = rfh->GetParent()) {
// Only check frames that qualify as DevTools targets, i.e. (local)? roots.
if (!RenderFrameDevToolsAgentHost::ShouldCreateDevToolsForHost(rfh))
continue;
auto* agent_host = static_cast<RenderFrameDevToolsAgentHost*>(
RenderFrameDevToolsAgentHost::GetFor(
navigation_request.frame_tree_node()));
RenderFrameDevToolsAgentHost::GetFor(rfh));
if (!agent_host)
return;
continue;
agent_host->OnNavigationRequestWillBeSent(navigation_request);
}
// Make sure both back-ends yield the same timestamp.
auto timestamp = base::TimeTicks::Now();
......
......@@ -86,10 +86,6 @@ RenderFrameDevToolsAgentHost* FindAgentHost(FrameTreeNode* frame_tree_node) {
return it == g_agent_host_instances.Get().end() ? nullptr : it->second;
}
bool ShouldCreateDevToolsForHost(RenderFrameHost* rfh) {
return rfh->IsCrossProcessSubframe() || !rfh->GetParent();
}
bool ShouldCreateDevToolsForNode(FrameTreeNode* ftn) {
return !ftn->parent() ||
(ftn->current_frame_host() &&
......@@ -142,6 +138,12 @@ scoped_refptr<DevToolsAgentHost> RenderFrameDevToolsAgentHost::GetOrCreateFor(
return result;
}
// static
bool RenderFrameDevToolsAgentHost::ShouldCreateDevToolsForHost(
RenderFrameHost* rfh) {
return rfh->IsCrossProcessSubframe() || !rfh->GetParent();
}
// static
scoped_refptr<DevToolsAgentHost>
RenderFrameDevToolsAgentHost::CreateForCrossProcessNavigation(
......@@ -614,7 +616,9 @@ void RenderFrameDevToolsAgentHost::OnPageScaleFactorChanged(
void RenderFrameDevToolsAgentHost::OnNavigationRequestWillBeSent(
const NavigationRequest& navigation_request) {
const auto& url = navigation_request.common_params().url;
GURL url = navigation_request.common_params().url;
if (url.SchemeIs(url::kJavaScriptScheme) && frame_host_)
url = frame_host_->GetLastCommittedURL();
std::vector<DevToolsSession*> restricted_sessions;
bool is_webui = frame_host_ && frame_host_->web_ui();
for (DevToolsSession* session : sessions()) {
......@@ -828,9 +832,16 @@ bool RenderFrameDevToolsAgentHost::ShouldAllowSession(
!manager->delegate()->AllowInspectingRenderFrameHost(frame_host_)) {
return false;
}
auto* root = FrameTreeNode::From(frame_host_);
for (FrameTreeNode* node : root->frame_tree()->SubtreeNodes(root)) {
// Note this may be called before navigation is committed.
return session->GetClient()->MayAttachToURL(
frame_host_->GetSiteInstance()->GetSiteURL(), frame_host_->web_ui());
RenderFrameHostImpl* rfh = node->current_frame_host();
const GURL& url = rfh->GetSiteInstance()->GetSiteURL();
if (!session->GetClient()->MayAttachToURL(url, rfh->web_ui())) {
return false;
}
}
return true;
}
void RenderFrameDevToolsAgentHost::UpdateResourceLoaderFactories() {
......
......@@ -61,6 +61,11 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
static scoped_refptr<DevToolsAgentHost> GetOrCreateFor(
FrameTreeNode* frame_tree_node);
// Whether the RFH passed may have associated DevTools agent host
// (i.e. the specified RFH is a local root). This does not indicate
// whether DevToolsAgentHost has actually been created.
static bool ShouldCreateDevToolsForHost(RenderFrameHost* rfh);
// This method is called when new frame is created during cross process
// navigation.
static scoped_refptr<DevToolsAgentHost> CreateForCrossProcessNavigation(
......
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