Skip to content

Commit

Permalink
chore: cherry-pick b321ac924772 from chromium (#34097)
Browse files Browse the repository at this point in the history
* chore: cherry-pick b321ac924772 from chromium

* fix patch

* fix patch compile error

Co-authored-by: Electron Bot <electron@github.com>
  • Loading branch information
nornagon and electron-bot committed May 24, 2022
1 parent 1c6d5ea commit d1b7571
Show file tree
Hide file tree
Showing 2 changed files with 194 additions and 0 deletions.
1 change: 1 addition & 0 deletions patches/chromium/.patches
Expand Up @@ -152,6 +152,7 @@ cherry-pick-5ff02e4d7368.patch
cherry-pick-5361d836aeb1.patch
cherry-pick-12ba78f3fa7a.patch
cherry-pick-5be8e065f43e.patch
cherry-pick-b321ac924772.patch
fsa_pass_file_ownership_to_worker_for_async_fsarfd_file_operations.patch
reland_fix_noopener_case_for_user_activation_consumption.patch
cherry-pick-99c3f3bfd507.patch
Expand Down
193 changes: 193 additions & 0 deletions patches/chromium/cherry-pick-b321ac924772.patch
@@ -0,0 +1,193 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dave Tapuska <dtapuska@chromium.org>
Date: Thu, 10 Mar 2022 02:35:27 +0000
Subject: Do not expose inner WebContents on scripting/getAllFrames.

Inner WebContents shouldn't be exposed for executeScript or getAllFrames
APIs. This is consistent with the API before crrev.com/f894f106
and crrev.com/c8de3b0a.

BUG=1301320,1261261

(cherry picked from commit 5c4e043324b3afd1be673ae2c0a5c00845bb0e86)

Change-Id: I86a5b09aa44c48319b7dd0a10e5442b8c803d4e5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3497565
Reviewed-by: Devlin Cronin <rdevlin.cronin@chromium.org>
Reviewed-by: Kevin McNee <mcnee@chromium.org>
Commit-Queue: Dave Tapuska <dtapuska@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#977769}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3514993
Cr-Commit-Position: refs/branch-heads/4758@{#1244}
Cr-Branched-From: 4a2cf4baf90326df19c3ee70ff987960d59a386e-refs/heads/main@{#950365}

diff --git a/chrome/browser/extensions/api/scripting/scripting_apitest.cc b/chrome/browser/extensions/api/scripting/scripting_apitest.cc
index e6d0aa8331816e4d2fe3e21fcede6b11b5ab00b2..37a35fda1ba5bda086764d0c1f8ee31f0d70f653 100644
--- a/chrome/browser/extensions/api/scripting/scripting_apitest.cc
+++ b/chrome/browser/extensions/api/scripting/scripting_apitest.cc
@@ -83,6 +83,15 @@ IN_PROC_BROWSER_TEST_F(ScriptingAPITest, SubFramesTests) {
ASSERT_TRUE(RunExtensionTest("scripting/sub_frames")) << message_;
}

+// Test validating we don't insert content into nested WebContents.
+IN_PROC_BROWSER_TEST_F(ScriptingAPITest, NestedWebContents) {
+ OpenURLInCurrentTab(
+ embedded_test_server()->GetURL("a.com", "/page_with_embedded_pdf.html"));
+
+ // From there, the test continues in the JS.
+ ASSERT_TRUE(RunExtensionTest("scripting/nested_web_contents")) << message_;
+}
+
IN_PROC_BROWSER_TEST_F(ScriptingAPITest, CSSInjection) {
OpenURLInCurrentTab(
embedded_test_server()->GetURL("example.com", "/simple.html"));
diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc b/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
index d18d496e9626990dc633b207a0c7482c026e6ed7..0486c08505e8f2f57229a775ada456ecf1a30a56 100644
--- a/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
+++ b/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
@@ -511,14 +511,21 @@ ExtensionFunction::ResponseAction WebNavigationGetAllFramesFunction::Run() {
std::vector<GetAllFrames::Results::DetailsType> result_list;

web_contents->ForEachFrame(base::BindRepeating(
- [](std::vector<GetAllFrames::Results::DetailsType>& result_list,
+ [](content::WebContents* web_contents,
+ std::vector<GetAllFrames::Results::DetailsType>& result_list,
content::RenderFrameHost* render_frame_host) {
+ // Don't expose inner WebContents for the getFrames API.
+ if (content::WebContents::FromRenderFrameHost(render_frame_host) !=
+ web_contents) {
+ return content::RenderFrameHost::FrameIterationAction::kSkipChildren;
+ }
+
auto* navigation_state =
FrameNavigationState::GetForCurrentDocument(render_frame_host);

if (!navigation_state ||
!FrameNavigationState::IsValidUrl(navigation_state->GetUrl())) {
- return;
+ return content::RenderFrameHost::FrameIterationAction::kContinue;
}

GetAllFrames::Results::DetailsType frame;
@@ -529,8 +536,9 @@ ExtensionFunction::ResponseAction WebNavigationGetAllFramesFunction::Run() {
frame.process_id = render_frame_host->GetProcess()->GetID();
frame.error_occurred = navigation_state->GetErrorOccurredInFrame();
result_list.push_back(std::move(frame));
+ return content::RenderFrameHost::FrameIterationAction::kContinue;
},
- std::ref(result_list)));
+ web_contents, std::ref(result_list)));

return RespondNow(ArgumentList(GetAllFrames::Results::Create(result_list)));
}
diff --git a/chrome/test/data/extensions/api_test/scripting/nested_web_contents/manifest.json b/chrome/test/data/extensions/api_test/scripting/nested_web_contents/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ee28c4149223ce82a7563270ee13c7f7c01d4a9
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/scripting/nested_web_contents/manifest.json
@@ -0,0 +1,8 @@
+{
+ "name": "Scripting API Test",
+ "manifest_version": 3,
+ "version": "0.1",
+ "permissions": ["scripting", "tabs", "webNavigation"],
+ "background": {"service_worker": "worker.js"},
+ "host_permissions": ["http://a.com/*", "http://b.com/*"]
+}
diff --git a/chrome/test/data/extensions/api_test/scripting/nested_web_contents/worker.js b/chrome/test/data/extensions/api_test/scripting/nested_web_contents/worker.js
new file mode 100644
index 0000000000000000000000000000000000000000..cea1287ece0a7397ac4cab3919ee2e7c12b02da8
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/scripting/nested_web_contents/worker.js
@@ -0,0 +1,41 @@
+// Copyright 2022 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.
+
+function injectedFunction() {
+ return location.pathname;
+}
+
+// Returns the single tab matching the given `query`.
+async function getSingleTab(query) {
+ const tabs = await chrome.tabs.query(query);
+ chrome.test.assertEq(1, tabs.length);
+ return tabs[0];
+}
+
+chrome.test.runTests([
+ async function nestedWebContents() {
+ const query = {url: 'http://a.com/*'};
+ let tab = await getSingleTab(query);
+ // There should be exactly 2 frames.
+ let frames = await chrome.webNavigation.getAllFrames({tabId: tab.id});
+ chrome.test.assertEq(2, frames.length);
+
+ // There should be exactly 2 results from executeScript.
+ let results = await chrome.scripting.executeScript({
+ target: {
+ tabId: tab.id,
+ allFrames: true,
+ },
+ func: injectedFunction,
+ });
+
+ // We see two frames here, the main frame and one for the embed. We should
+ // *not* see the third "embed within the embed" created by the PDF
+ // reader.
+ chrome.test.assertEq(2, results.length);
+ chrome.test.assertEq('/page_with_embedded_pdf.html', results[0].result);
+ chrome.test.assertEq('/pdf/test.pdf', results[1].result);
+ chrome.test.succeed();
+ },
+]);
diff --git a/extensions/browser/script_executor.cc b/extensions/browser/script_executor.cc
index b5b8c8d4b31e3e9bdd7d96c79cc361ace45182fd..69cea43df78ae2d314bd7634c5eb6112f9dcedea 100644
--- a/extensions/browser/script_executor.cc
+++ b/extensions/browser/script_executor.cc
@@ -90,24 +90,32 @@ class Handler : public content::WebContentsObserver {
// `pending_render_frames_` and add them if they are alive (and not already
// contained in `pending_frames`).
if (scope == ScriptExecutor::INCLUDE_SUB_FRAMES) {
- auto append_frame =
- [](std::vector<content::RenderFrameHost*>* pending_frames,
- content::RenderFrameHost* frame) {
- if (!frame->IsRenderFrameLive() ||
- base::Contains(*pending_frames, frame)) {
- return;
- }
-
- pending_frames->push_back(frame);
- };
+ auto append_frame = [](content::WebContents* web_contents,
+ std::vector<content::RenderFrameHost*>*
+ pending_frames,
+ content::RenderFrameHost* frame) {
+ // Avoid inner web contents. If we need to execute scripts on
+ // inner WebContents this class needs to be updated.
+ // See crbug.com/1301320.
+ if (content::WebContents::FromRenderFrameHost(frame) != web_contents) {
+ return content::RenderFrameHost::FrameIterationAction::kSkipChildren;
+ }
+ if (!frame->IsRenderFrameLive() ||
+ base::Contains(*pending_frames, frame)) {
+ return content::RenderFrameHost::FrameIterationAction::kContinue;
+ }
+
+ pending_frames->push_back(frame);
+ return content::RenderFrameHost::FrameIterationAction::kContinue;
+ };

// We iterate over the requested frames. Note we can't use an iterator
// as the for loop will mutate `pending_render_frames_`.
size_t requested_frame_count = pending_render_frames_.size();
for (size_t i = 0; i < requested_frame_count; ++i) {
- auto* frame = pending_render_frames_.at(i);
- frame->ForEachRenderFrameHost(
- base::BindRepeating(append_frame, &pending_render_frames_));
+ pending_render_frames_.at(i)->ForEachRenderFrameHost(
+ base::BindRepeating(append_frame, web_contents,
+ &pending_render_frames_));
}
}

0 comments on commit d1b7571

Please sign in to comment.