CVE-2026-79106
Overview
Background
- Touch Selection Quick Menu
- the small floating menu (Copy/Paste/etc.) that Chrome shows near a touch text selection, positioned from selection edge coordinates reported by the renderer.
- `TouchSelectionControllerClientChildFrame`
- the browser-process client that takes a child (sub)frame’s selection bounds and transforms them into the root view’s coordinate space so the menu can be placed.
- `gfx::SelectionBound`
- a structure holding the
edge_start/edge_endandvisible_edge_start/visible_edge_endpoints describing one end of a selection. - `TransformPointToRootCoordSpaceF`
RenderWidgetHostViewChildFrame’s method that maps a point from a child frame’s local space up into the root view’s space.
Root Cause Analysis
In TouchSelectionControllerClientChildFrame::TransformSelectionBoundsAndUpdate, the browser process took the renderer-supplied selection_start_ and selection_end_ bounds and passed each edge point directly through rwhv_->TransformPointToRootCoordSpaceF() before handing them to manager_->UpdateClientSelectionBounds(). A compromised or malicious child-frame renderer controls the selection metadata it reports, so it could send edge coordinates far outside its own visual rectangle (the regression test uses (-50,-50) and (200,200) against a 100x100 view). Because no code constrained those coordinates to the child frame’s actual geometry, the resulting root-space coordinates could place the Quick Menu anywhere in the top-level window, outside the reporting frame’s visual area.
The fix builds local_bounds from rwhv_->GetViewBounds().size() and runs every edge point through the new ClampSelectionBoundToRect (via ClampPointToRect using std::clamp) before transformation, so all reported points are forced back into the child frame’s own rectangle. This restores the invariant that a subframe can only influence selection UI within its own visual boundaries.
Attack Path
- Compromise a child frame An attacker runs code in a subframe (e.g. a cross-origin iframe) renderer, or fully compromises that renderer process.
- Report spoofed selection bounds
The renderer sends selection metadata whose edge points lie well outside the frame’s own
100x100-style visual rectangle, e.g. negative or oversized coordinates. - Unvalidated transform
TransformSelectionBoundsAndUpdatepasses those raw points straight intoTransformPointToRootCoordSpaceF, mapping them into root-window space without clamping. - Out-of-bounds menu placement
UpdateClientSelectionBoundsreceives the spoofed root-space bounds and the Touch Selection Quick Menu is drawn at coordinates outside the reporting frame’s area, enabling UI spoofing/misplacement (inferred as the concrete UI consequence from the commit message).
Impact Assessment
Changed Functions
| Function | Change | Notes |
|---|---|---|
TransformSelectionBoundsAndUpdatecontent/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc |
modified | |
ifcontent/browser/renderer_host/render_widget_host_view_child_frame.cc |
modified | |
TestTouchSelectionControllerClientManagercontent/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc |
modified | |
MockRenderWidgetHostViewcontent/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc |
modified | |
RenderWidgetHostViewChildFrameTestcontent/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc |
modified | |
TEST_Fcontent/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc |
modified |
Files Changed
content/browser/renderer_host/render_widget_host_view_child_frame.cccontent/browser/renderer_host/render_widget_host_view_child_frame_unittest.cccontent/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
Audit Directions
- Renderer-reported geometryAudit every browser-process consumer of renderer-supplied coordinates/bounds (selection, IME, drag, tooltips) that transforms them to root space; confirm each clamps to the reporting view’s bounds first.
- Child-frame to root coordinate transformsWherever
TransformPointToRootCoordSpaceFor similar transforms are fed subframe values, verify the values were validated against the subframe’s local rectangle before mapping. - Optional observer registrationCheck other
Add/RemoveInputEventObserver-style calls for missing null guards like the one added here, especially on platform-specific (IS_ANDROID) paths.
Patch
From 65494ad63c8668d6cebb76fb15ea3105592a5e09 Mon Sep 17 00:00:00 2001
From: Zhenyao Mo <zmo@chromium.org>
Date: Thu, 16 Jul 2026 08:57:32 -0700
Subject: [PATCH] Clamp subframe touch selection bounds to subframe view bounds
A compromised child frame renderer can send selection metadata with
coordinates outside its visual boundaries. When transforming these
bounds to the root view coordinate space without validation, the browser
process could display the Touch Selection Quick Menu at spoofed
coordinates outside the reporting frame's visual area.
This CL updates TouchSelectionControllerClientChildFrame to clamp all
reported selection bounds to the local view geometry of the child frame
before transforming them to root coordinate space, preventing
out-of-bounds menu placement.
Bug: 497456156
Test: RenderWidgetHostViewChildFrameTest.SelectionBoundsClampedToViewBounds
Change-Id: I1b5304b7233f0bafa67599917e0d59ab5b504990
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8100702
Commit-Queue: Zhenyao Mo <zmo@chromium.org>
Reviewed-by: Dave Tapuska <dtapuska@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1663152}
---
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc b/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
index b16b601..b1dcbcf4 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
@@ -4,6 +4,8 @@
#include "content/browser/renderer_host/input/touch_selection_controller_client_child_frame.h"
+#include <algorithm>
+
#include "base/check.h"
#include "base/notreached.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
@@ -16,11 +18,33 @@
#include "ui/base/mojom/menu_source_type.mojom.h"
#include "ui/base/ui_base_features.h"
#include "ui/gfx/geometry/point_conversions.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size_f.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/touch_selection/touch_editing_controller.h"
namespace content {
+namespace {
+
+gfx::PointF ClampPointToRect(const gfx::PointF& point, const gfx::RectF& rect) {
+ return gfx::PointF(std::clamp(point.x(), rect.x(), rect.right()),
+ std::clamp(point.y(), rect.y(), rect.bottom()));
+}
+
+gfx::SelectionBound ClampSelectionBoundToRect(const gfx::SelectionBound& bound,
+ const gfx::RectF& rect) {
+ gfx::SelectionBound clamped_bound(bound);
+ clamped_bound.SetEdge(ClampPointToRect(bound.edge_start(), rect),
+ ClampPointToRect(bound.edge_end(), rect));
+ clamped_bound.SetVisibleEdge(
+ ClampPointToRect(bound.visible_edge_start(), rect),
+ ClampPointToRect(bound.visible_edge_end(), rect));
+ return clamped_bound;
+}
+
+} // namespace
+
TouchSelectionControllerClientChildFrame::
TouchSelectionControllerClientChildFrame(
RenderWidgetHostViewChildFrame* rwhv,
@@ -54,27 +78,34 @@
void TouchSelectionControllerClientChildFrame::
TransformSelectionBoundsAndUpdate() {
- gfx::SelectionBound transformed_selection_start(selection_start_);
- gfx::SelectionBound transformed_selection_end(selection_end_);
+ gfx::RectF local_bounds(gfx::SizeF(rwhv_->GetViewBounds().size()));
+ gfx::SelectionBound clamped_selection_start =
+ ClampSelectionBoundToRect(selection_start_, local_bounds);
+ gfx::SelectionBound clamped_selection_end =
+ ClampSelectionBoundToRect(selection_end_, local_bounds);
+ gfx::SelectionBound transformed_selection_start(clamped_selection_start);
+ gfx::SelectionBound transformed_selection_end(clamped_selection_end);
// TODO(wjmaclean): Get the transform between the views to lower the
// overhead here, instead of calling the transform functions four times.
- transformed_selection_start.SetEdge(
- rwhv_->TransformPointToRootCoordSpaceF(selection_start_.edge_start()),
- rwhv_->TransformPointToRootCoordSpaceF(selection_start_.edge_end()));
+ transformed_selection_start.SetEdge(rwhv_->TransformPointToRootCoordSpaceF(
+ clamped_selection_start.edge_start()),
+ rwhv_->TransformPointToRootCoordSpaceF(
+ clamped_selection_start.edge_end()));
transformed_selection_start.SetVisibleEdge(
rwhv_->TransformPointToRootCoordSpaceF(
- selection_start_.visible_edge_start()),
+ clamped_selection_start.visible_edge_start()),
rwhv_->TransformPointToRootCoordSpaceF(
- selection_start_.visible_edge_end()));
+ clamped_selection_start.visible_edge_end()));
transformed_selection_end.SetEdge(
- rwhv_->TransformPointToRootCoordSpaceF(selection_end_.edge_start()),
- rwhv_->TransformPointToRootCoordSpaceF(selection_end_.edge_end()));
+ rwhv_->TransformPointToRootCoordSpaceF(
+ clamped_selection_end.edge_start()),
+ rwhv_->TransformPointToRootCoordSpaceF(clamped_selection_end.edge_end()));
transformed_selection_end.SetVisibleEdge(
rwhv_->TransformPointToRootCoordSpaceF(
- selection_end_.visible_edge_start()),
+ clamped_selection_end.visible_edge_start()),
rwhv_->TransformPointToRootCoordSpaceF(
- selection_end_.visible_edge_end()));
+ clamped_selection_end.visible_edge_end()));
manager_->UpdateClientSelectionBounds(transformed_selection_start,
transformed_selection_end, this, this);
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
index fb05dcf2..7c4702a3 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -120,7 +120,9 @@
manager->RemoveObserver(this);
#if BUILDFLAG(IS_ANDROID)
auto* observer = root_view->GetTouchSelectionControllerInputObserver();
- host()->RemoveInputEventObserver(observer);
+ if (observer) {
+ host()->RemoveInputEventObserver(observer);
+ }
#endif
}
} else {
@@ -188,7 +190,9 @@
#if BUILDFLAG(IS_ANDROID)
auto* observer = root_view->GetTouchSelectionControllerInputObserver();
- host()->AddInputEventObserver(observer);
+ if (observer) {
+ host()->AddInputEventObserver(observer);
+ }
#endif
}
}
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
index 288bce5..0d5018b 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
@@ -15,6 +15,7 @@
#include "base/task/single_thread_task_runner.h"
#include "base/test/task_environment.h"
#include "build/build_config.h"
+#include "cc/trees/render_frame_metadata.h"
#include "components/input/child_frame_input_helper.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/test/begin_frame_args_test.h"
@@ -49,6 +50,7 @@
#include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h"
#include "ui/base/ui_base_features.h"
#include "ui/compositor/compositor.h"
+#include "ui/gfx/selection_bound.h"
#if BUILDFLAG(IS_WIN)
#include "components/stylus_handwriting/win/features.h"
@@ -132,12 +134,71 @@
raw_ptr<RenderWidgetHostViewBase> root_host_view_ = nullptr;
};
+class TestTouchSelectionControllerClientManager
+ : public TouchSelectionControllerClientManager {
+ public:
+ TestTouchSelectionControllerClientManager() = default;
+ ~TestTouchSelectionControllerClientManager() override = default;
+
+ void DidStopFlinging() override {}
+ void OnSwipeToMoveCursorBegin() override {}
+ void OnSwipeToMoveCursorEnd() override {}
+ void OnClientHitTestRegionUpdated(
+ ui::TouchSelectionControllerClient* client) override {}
+ void UpdateClientSelectionBounds(
+ const gfx::SelectionBound& start,
+ const gfx::SelectionBound& end,
+ ui::TouchSelectionControllerClient* client,
+ ui::TouchSelectionMenuClient* menu_client) override {
+ last_selection_start_ = start;
+ last_selection_end_ = end;
+ }
+ void InvalidateClient(ui::TouchSelectionControllerClient* client) override {}
+ ui::TouchSelectionController* GetTouchSelectionController() override {
+ return nullptr;
+ }
+ void AddObserver(Observer* observer) override {}
+ void RemoveObserver(Observer* observer) override {}
+
+ const gfx::SelectionBound& last_selection_start() const {
+ return last_selection_start_;
+ }
+ const gfx::SelectionBound& last_selection_end() const {
+ return last_selection_end_;
+ }
+
+ private:
+ gfx::SelectionBound last_selection_start_;
+ gfx::SelectionBound last_selection_end_;
+};
+
class MockRenderWidgetHostView : public TestRenderWidgetHostView {
public:
explicit MockRenderWidgetHostView(RenderWidgetHost* rwh)
: TestRenderWidgetHostView(rwh) {}
~MockRenderWidgetHostView() override = default;
+ TouchSelectionControllerClientManager*
+ GetTouchSelectionControllerClientManager() override {
+ return &selection_manager_;
+ }
+
+ bool TransformPointToCoordSpaceForView(
+ const gfx::PointF& point,
+ input::RenderWidgetHostViewInput* target_view,
+ gfx::PointF* transformed_point) override {
+ *transformed_point = point;
+ return true;
+ }
+
+ bool TransformPointToLocalCoordSpace(
+ const gfx::PointF& point,
+ const viz::FrameSinkId& original_frame_sink_id,
+ gfx::PointF* transformed_point) override {
+ *transformed_point = point;
+ return true;
+ }
+
#if BUILDFLAG(IS_MAC)
MOCK_METHOD(void,
ShowSharePicker,
@@ -148,6 +209,13 @@
blink::mojom::ShareService::ShareCallback callback),
(override));
#endif
+
+ TestTouchSelectionControllerClientManager* selection_manager() {
+ return &selection_manager_;
+ }
+
+ private:
+ TestTouchSelectionControllerClientManager selection_manager_;
};
class RenderWidgetHostViewChildFrameTest
@@ -704,4 +772,58 @@
}
#endif // BUILDFLAG(IS_WIN)
+TEST_F(RenderWidgetHostViewChildFrameTest, SelectionBoundsClampedToViewBounds) {
+ auto root_view =
+ std::make_unique<testing::NiceMock<MockRenderWidgetHostView>>(
+ widget_host_.get());
+ RenderWidgetHostViewChildFrame* child_view =
+ RenderWidgetHostViewChildFrame::Create(widget_host_.get(),
+ display::ScreenInfos());
+ std::unique_ptr<MockFrameConnector> connector =
+ std::make_unique<MockFrameConnector>();
+ connector->SetRootRenderWidgetHostView(root_view.get());
+ connector->SetView(child_view, false);
+
+ // Set local frame bounds and size DIP to 100x100.
+ connector->SetRectInParentView(gfx::Rect(0, 0, 100, 100));
+ connector->SetLocalFrameSize(gfx::Size(100, 100));
+ child_view->SetSize(gfx::Size(100, 100));
+
+ // Report selection bounds with spoofed coordinates far outside [0, 0, 100,
+ // 100].
+ cc::RenderFrameMetadata metadata;
+ metadata.selection.start.set_type(gfx::SelectionBound::LEFT);
+ metadata.selection.start.set_visible(true);
+ metadata.selection.start.SetEdge(gfx::PointF(-50.0f, -50.0f),
+ gfx::PointF(-50.0f, -10.0f));
+ metadata.selection.start.SetVisibleEdge(gfx::PointF(-50.0f, -50.0f),
+ gfx::PointF(-50.0f, -10.0f));
+
+ metadata.selection.end.set_type(gfx::SelectionBound::RIGHT);
+ metadata.selection.end.set_visible(true);
+ metadata.selection.end.SetEdge(gfx::PointF(200.0f, 200.0f),
+ gfx::PointF(200.0f, 250.0f));
+ metadata.selection.end.SetVisibleEdge(gfx::PointF(200.0f, 200.0f),
+ gfx::PointF(200.0f, 250.0f));
+
+ widget_host_->render_frame_metadata_provider()
+ ->SetLastRenderFrameMetadataForTest(metadata);
+ child_view->OnRenderFrameMetadataChangedAfterActivation(base::TimeTicks());
+
+ // Verify that start and end bounds sent to the manager were clamped to [0,
+ // 100].
+ gfx::SelectionBound start =
+ root_view->selection_manager()->last_selection_start();
+ gfx::SelectionBound end =
+ root_view->selection_manager()->last_selection_end();
+
+ EXPECT_EQ(gfx::PointF(0.0f, 0.0f), start.edge_start());
+ EXPECT_EQ(gfx::PointF(0.0f, 0.0f), start.edge_end());
+ EXPECT_EQ(gfx::PointF(100.0f, 100.0f), end.edge_start());
+ EXPECT_EQ(gfx::PointF(100.0f, 100.0f), end.edge_end());
+
+ child_view->Destroy();
+ connector->SetRootRenderWidgetHostView(nullptr);
+}
+
} // namespace content
Regression Test / PoC
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
index 288bce5..0d5018b 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
@@ -15,6 +15,7 @@
#include "base/task/single_thread_task_runner.h"
#include "base/test/task_environment.h"
#include "build/build_config.h"
+#include "cc/trees/render_frame_metadata.h"
#include "components/input/child_frame_input_helper.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/test/begin_frame_args_test.h"
@@ -49,6 +50,7 @@
#include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h"
#include "ui/base/ui_base_features.h"
#include "ui/compositor/compositor.h"
+#include "ui/gfx/selection_bound.h"
#if BUILDFLAG(IS_WIN)
#include "components/stylus_handwriting/win/features.h"
@@ -132,12 +134,71 @@
raw_ptr<RenderWidgetHostViewBase> root_host_view_ = nullptr;
};
+class TestTouchSelectionControllerClientManager
+ : public TouchSelectionControllerClientManager {
+ public:
+ TestTouchSelectionControllerClientManager() = default;
+ ~TestTouchSelectionControllerClientManager() override = default;
+
+ void DidStopFlinging() override {}
+ void OnSwipeToMoveCursorBegin() override {}
+ void OnSwipeToMoveCursorEnd() override {}
+ void OnClientHitTestRegionUpdated(
+ ui::TouchSelectionControllerClient* client) override {}
+ void UpdateClientSelectionBounds(
+ const gfx::SelectionBound& start,
+ const gfx::SelectionBound& end,
+ ui::TouchSelectionControllerClient* client,
+ ui::TouchSelectionMenuClient* menu_client) override {
+ last_selection_start_ = start;
+ last_selection_end_ = end;
+ }
+ void InvalidateClient(ui::TouchSelectionControllerClient* client) override {}
+ ui::TouchSelectionController* GetTouchSelectionController() override {
+ return nullptr;
+ }
+ void AddObserver(Observer* observer) override {}
+ void RemoveObserver(Observer* observer) override {}
+
+ const gfx::SelectionBound& last_selection_start() const {
+ return last_selection_start_;
+ }
+ const gfx::SelectionBound& last_selection_end() const {
+ return last_selection_end_;
+ }
+
+ private:
+ gfx::SelectionBound last_selection_start_;
+ gfx::SelectionBound last_selection_end_;
+};
+
class MockRenderWidgetHostView : public TestRenderWidgetHostView {
public:
explicit MockRenderWidgetHostView(RenderWidgetHost* rwh)
: TestRenderWidgetHostView(rwh) {}
~MockRenderWidgetHostView() override = default;
+ TouchSelectionControllerClientManager*
+ GetTouchSelectionControllerClientManager() override {
+ return &selection_manager_;
+ }
+
+ bool TransformPointToCoordSpaceForView(
+ const gfx::PointF& point,
+ input::RenderWidgetHostViewInput* target_view,
+ gfx::PointF* transformed_point) override {
+ *transformed_point = point;
+ return true;
+ }
+
+ bool TransformPointToLocalCoordSpace(
+ const gfx::PointF& point,
+ const viz::FrameSinkId& original_frame_sink_id,
+ gfx::PointF* transformed_point) override {
+ *transformed_point = point;
+ return true;
+ }
+
#if BUILDFLAG(IS_MAC)
MOCK_METHOD(void,
ShowSharePicker,
@@ -148,6 +209,13 @@
blink::mojom::ShareService::ShareCallback callback),
(override));
#endif
+
+ TestTouchSelectionControllerClientManager* selection_manager() {
+ return &selection_manager_;
+ }
+
+ private:
+ TestTouchSelectionControllerClientManager selection_manager_;
};
class RenderWidgetHostViewChildFrameTest
@@ -704,4 +772,58 @@
}
#endif // BUILDFLAG(IS_WIN)
+TEST_F(RenderWidgetHostViewChildFrameTest, SelectionBoundsClampedToViewBounds) {
+ auto root_view =
+ std::make_unique<testing::NiceMock<MockRenderWidgetHostView>>(
+ widget_host_.get());
+ RenderWidgetHostViewChildFrame* child_view =
+ RenderWidgetHostViewChildFrame::Create(widget_host_.get(),
+ display::ScreenInfos());
+ std::unique_ptr<MockFrameConnector> connector =
+ std::make_unique<MockFrameConnector>();
+ connector->SetRootRenderWidgetHostView(root_view.get());
+ connector->SetView(child_view, false);
+
+ // Set local frame bounds and size DIP to 100x100.
+ connector->SetRectInParentView(gfx::Rect(0, 0, 100, 100));
+ connector->SetLocalFrameSize(gfx::Size(100, 100));
+ child_view->SetSize(gfx::Size(100, 100));
+
+ // Report selection bounds with spoofed coordinates far outside [0, 0, 100,
+ // 100].
+ cc::RenderFrameMetadata metadata;
+ metadata.selection.start.set_type(gfx::SelectionBound::LEFT);
+ metadata.selection.start.set_visible(true);
+ metadata.selection.start.SetEdge(gfx::PointF(-50.0f, -50.0f),
+ gfx::PointF(-50.0f, -10.0f));
+ metadata.selection.start.SetVisibleEdge(gfx::PointF(-50.0f, -50.0f),
+ gfx::PointF(-50.0f, -10.0f));
+
+ metadata.selection.end.set_type(gfx::SelectionBound::RIGHT);
+ metadata.selection.end.set_visible(true);
+ metadata.selection.end.SetEdge(gfx::PointF(200.0f, 200.0f),
+ gfx::PointF(200.0f, 250.0f));
+ metadata.selection.end.SetVisibleEdge(gfx::PointF(200.0f, 200.0f),
+ gfx::PointF(200.0f, 250.0f));
+
+ widget_host_->render_frame_metadata_provider()
+ ->SetLastRenderFrameMetadataForTest(metadata);
+ child_view->OnRenderFrameMetadataChangedAfterActivation(base::TimeTicks());
+
+ // Verify that start and end bounds sent to the manager were clamped to [0,
+ // 100].
+ gfx::SelectionBound start =
+ root_view->selection_manager()->last_selection_start();
+ gfx::SelectionBound end =
+ root_view->selection_manager()->last_selection_end();
+
+ EXPECT_EQ(gfx::PointF(0.0f, 0.0f), start.edge_start());
+ EXPECT_EQ(gfx::PointF(0.0f, 0.0f), start.edge_end());
+ EXPECT_EQ(gfx::PointF(100.0f, 100.0f), end.edge_start());
+ EXPECT_EQ(gfx::PointF(100.0f, 100.0f), end.edge_end());
+
+ child_view->Destroy();
+ connector->SetRootRenderWidgetHostView(nullptr);
+}
+
} // namespace content