Browse Source

chore: cherry-pick b321ac924772 from chromium (#34097)

* chore: cherry-pick b321ac924772 from chromium

* fix patch

* fix patch compile error

Co-authored-by: Electron Bot <[email protected]>
Jeremy Rose 2 years ago
parent
commit
d1b75716ad
2 changed files with 194 additions and 0 deletions
  1. 1 0
      patches/chromium/.patches
  2. 193 0
      patches/chromium/cherry-pick-b321ac924772.patch

+ 1 - 0
patches/chromium/.patches

@@ -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

+ 193 - 0
patches/chromium/cherry-pick-b321ac924772.patch

@@ -0,0 +1,193 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Dave Tapuska <[email protected]>
+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 <[email protected]>
+Reviewed-by: Kevin McNee <[email protected]>
+Commit-Queue: Dave Tapuska <[email protected]>
+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_));
+       }
+     }
+