blob: 91f836230c3bec943e30702aa0342331b948f3d7 [file] [log] [blame]
[email protected]9b159a52013-10-03 17:24:551// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
danakjc492bf82020-09-09 20:02:445#include "content/browser/renderer_host/frame_tree.h"
[email protected]9b159a52013-10-03 17:24:556
avib7348942015-12-25 20:57:107#include <stddef.h>
8
[email protected]9b159a52013-10-03 17:24:559#include <queue>
Lukasz Anforowicz7bfb2e92017-11-22 17:19:4510#include <set>
dcheng29f5a6c2015-08-31 21:43:2711#include <utility>
[email protected]9b159a52013-10-03 17:24:5512
13#include "base/bind.h"
14#include "base/callback.h"
[email protected]20edca72014-08-14 10:27:5315#include "base/lazy_instance.h"
dcheng9bfa5162016-04-09 01:00:5716#include "base/memory/ptr_util.h"
Lowell Manners75055a132019-10-11 10:30:2917#include "base/stl_util.h"
Pavel Feldman25234722017-10-11 02:49:0618#include "base/unguessable_token.h"
danakjc492bf82020-09-09 20:02:4419#include "content/browser/renderer_host/frame_tree_node.h"
20#include "content/browser/renderer_host/navigation_controller_impl.h"
21#include "content/browser/renderer_host/navigation_entry_impl.h"
22#include "content/browser/renderer_host/navigation_request.h"
23#include "content/browser/renderer_host/navigator.h"
24#include "content/browser/renderer_host/navigator_delegate.h"
25#include "content/browser/renderer_host/render_frame_host_factory.h"
26#include "content/browser/renderer_host/render_frame_host_impl.h"
27#include "content/browser/renderer_host/render_frame_proxy_host.h"
[email protected]94d0cc12013-12-18 00:07:4128#include "content/browser/renderer_host/render_view_host_factory.h"
29#include "content/browser/renderer_host/render_view_host_impl.h"
japhet98e9bd82016-06-28 23:48:4530#include "content/common/content_switches_internal.h"
alexmos3fcd0ca2015-10-23 18:18:3331#include "content/common/input_messages.h"
Blink Reformata30d4232018-04-07 15:31:0632#include "third_party/blink/public/common/frame/frame_policy.h"
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:5433#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom.h"
[email protected]9b159a52013-10-03 17:24:5534
35namespace content {
36
37namespace {
[email protected]20edca72014-08-14 10:27:5338
dcheng57e39e22016-01-21 00:25:3839// Helper function to collect SiteInstances involved in rendering a single
40// FrameTree (which is a subset of SiteInstances in main frame's proxy_hosts_
41// because of openers).
42std::set<SiteInstance*> CollectSiteInstances(FrameTree* tree) {
43 std::set<SiteInstance*> instances;
44 for (FrameTreeNode* node : tree->Nodes())
45 instances.insert(node->current_frame_host()->GetSiteInstance());
46 return instances;
alexmos3fcd0ca2015-10-23 18:18:3347}
48
[email protected]9b159a52013-10-03 17:24:5549} // namespace
50
vmpstr33895d992016-02-24 20:55:2151FrameTree::NodeIterator::NodeIterator(const NodeIterator& other) = default;
52
dcheng57e39e22016-01-21 00:25:3853FrameTree::NodeIterator::~NodeIterator() {}
54
55FrameTree::NodeIterator& FrameTree::NodeIterator::operator++() {
Alex Moshchuk27caae82017-09-11 23:11:1856 if (current_node_ != root_of_subtree_to_skip_) {
57 for (size_t i = 0; i < current_node_->child_count(); ++i) {
58 FrameTreeNode* child = current_node_->child_at(i);
59 queue_.push(child);
60 }
dcheng57e39e22016-01-21 00:25:3861 }
62
63 if (!queue_.empty()) {
64 current_node_ = queue_.front();
65 queue_.pop();
66 } else {
67 current_node_ = nullptr;
68 }
69
70 return *this;
71}
72
73bool FrameTree::NodeIterator::operator==(const NodeIterator& rhs) const {
74 return current_node_ == rhs.current_node_;
75}
76
77FrameTree::NodeIterator::NodeIterator(FrameTreeNode* starting_node,
Alex Moshchuk27caae82017-09-11 23:11:1878 FrameTreeNode* root_of_subtree_to_skip)
79 : current_node_(starting_node),
80 root_of_subtree_to_skip_(root_of_subtree_to_skip) {}
dcheng57e39e22016-01-21 00:25:3881
82FrameTree::NodeIterator FrameTree::NodeRange::begin() {
W. James MacLeance3176d2019-10-18 04:01:4583 // We shouldn't be attempting a frame tree traversal while the tree is
84 // being constructed.
85 DCHECK(root_->current_frame_host());
Alex Moshchuk27caae82017-09-11 23:11:1886 return NodeIterator(root_, root_of_subtree_to_skip_);
dcheng57e39e22016-01-21 00:25:3887}
88
89FrameTree::NodeIterator FrameTree::NodeRange::end() {
90 return NodeIterator(nullptr, nullptr);
91}
92
kenrb61b6c252016-03-22 17:37:1593FrameTree::NodeRange::NodeRange(FrameTreeNode* root,
Alex Moshchuk27caae82017-09-11 23:11:1894 FrameTreeNode* root_of_subtree_to_skip)
95 : root_(root), root_of_subtree_to_skip_(root_of_subtree_to_skip) {}
dcheng57e39e22016-01-21 00:25:3896
Fergal Daly09d6c762020-05-29 02:05:1897FrameTree::FrameTree(NavigationControllerImpl* navigation_controller,
98 NavigatorDelegate* navigator_delegate,
[email protected]92404c62013-12-04 16:40:4699 RenderFrameHostDelegate* render_frame_delegate,
[email protected]fa944cb82013-11-15 17:51:21100 RenderViewHostDelegate* render_view_delegate,
101 RenderWidgetHostDelegate* render_widget_delegate,
[email protected]b0936d22013-11-28 06:47:36102 RenderFrameHostManager::Delegate* manager_delegate)
[email protected]92404c62013-12-04 16:40:46103 : render_frame_delegate_(render_frame_delegate),
104 render_view_delegate_(render_view_delegate),
[email protected]fa944cb82013-11-15 17:51:21105 render_widget_delegate_(render_widget_delegate),
106 manager_delegate_(manager_delegate),
Fergal Daly09d6c762020-05-29 02:05:18107 navigator_(navigation_controller, navigator_delegate),
[email protected]94d0cc12013-12-18 00:07:41108 root_(new FrameTreeNode(this,
xiaochengh98488162016-05-19 15:17:59109 nullptr,
dcheng860817a2015-05-22 03:16:56110 // The top-level frame must always be in a
111 // document scope.
Antonio Gomes9d5c1ef2020-04-30 20:56:41112 blink::mojom::TreeScopeType::kDocument,
alexmos6e0ee0c2015-05-01 18:57:34113 std::string(),
lukasza464d8692016-02-22 19:26:32114 std::string(),
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45115 false,
Pavel Feldman25234722017-10-11 02:49:06116 base::UnguessableToken::Create(),
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:54117 blink::mojom::FrameOwnerProperties(),
Antonio Gomes58d38062020-04-30 01:50:14118 blink::mojom::FrameOwnerElementType::kNone)),
thestige62f7382016-11-08 18:31:39119 focused_frame_tree_node_id_(FrameTreeNode::kFrameTreeNodeInvalidId),
lazyboy70605c32015-11-03 01:27:31120 load_progress_(0.0) {}
[email protected]9b159a52013-10-03 17:24:55121
122FrameTree::~FrameTree() {
nick70b782d2015-10-06 17:37:04123 delete root_;
124 root_ = nullptr;
[email protected]9b159a52013-10-03 17:24:55125}
126
vishal.b782eb5d2015-04-29 12:22:57127FrameTreeNode* FrameTree::FindByID(int frame_tree_node_id) {
dcheng57e39e22016-01-21 00:25:38128 for (FrameTreeNode* node : Nodes()) {
129 if (node->frame_tree_node_id() == frame_tree_node_id)
130 return node;
131 }
132 return nullptr;
[email protected]9b159a52013-10-03 17:24:55133}
134
nasko479ea5a2015-02-14 00:03:04135FrameTreeNode* FrameTree::FindByRoutingID(int process_id, int routing_id) {
dmazzoni0b5d2482014-09-10 19:45:57136 RenderFrameHostImpl* render_frame_host =
137 RenderFrameHostImpl::FromID(process_id, routing_id);
138 if (render_frame_host) {
139 FrameTreeNode* result = render_frame_host->frame_tree_node();
140 if (this == result->frame_tree())
141 return result;
142 }
143
144 RenderFrameProxyHost* render_frame_proxy_host =
145 RenderFrameProxyHost::FromID(process_id, routing_id);
146 if (render_frame_proxy_host) {
147 FrameTreeNode* result = render_frame_proxy_host->frame_tree_node();
148 if (this == result->frame_tree())
149 return result;
150 }
151
creis6a93a812015-04-24 23:13:17152 return nullptr;
153}
154
155FrameTreeNode* FrameTree::FindByName(const std::string& name) {
156 if (name.empty())
nick70b782d2015-10-06 17:37:04157 return root_;
creis6a93a812015-04-24 23:13:17158
dcheng57e39e22016-01-21 00:25:38159 for (FrameTreeNode* node : Nodes()) {
160 if (node->frame_name() == name)
161 return node;
[email protected]9b159a52013-10-03 17:24:55162 }
dcheng57e39e22016-01-21 00:25:38163
164 return nullptr;
165}
166
167FrameTree::NodeRange FrameTree::Nodes() {
Alex Moshchuk27caae82017-09-11 23:11:18168 return NodesExceptSubtree(nullptr);
dcheng57e39e22016-01-21 00:25:38169}
170
kenrb61b6c252016-03-22 17:37:15171FrameTree::NodeRange FrameTree::SubtreeNodes(FrameTreeNode* subtree_root) {
172 return NodeRange(subtree_root, nullptr);
173}
174
Alex Moshchuk27caae82017-09-11 23:11:18175FrameTree::NodeRange FrameTree::NodesExceptSubtree(FrameTreeNode* node) {
176 return NodeRange(root_, node);
[email protected]9b159a52013-10-03 17:24:55177}
178
Lucas Furukawa Gadani99125822019-01-03 15:41:49179FrameTreeNode* FrameTree::AddFrame(
Alexander Timin381e7e182020-04-28 19:04:03180 RenderFrameHostImpl* parent,
Balazs Engedyba034e72017-10-27 22:26:28181 int process_id,
182 int new_routing_id,
Gyuyoung Kim6c9ce9022019-11-26 05:40:08183 mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
184 interface_provider_receiver,
Oksana Zhuravlovafee097c2019-07-26 17:01:30185 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
186 browser_interface_broker_receiver,
Antonio Gomes9d5c1ef2020-04-30 20:56:41187 blink::mojom::TreeScopeType scope,
Balazs Engedyba034e72017-10-27 22:26:28188 const std::string& frame_name,
189 const std::string& frame_unique_name,
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45190 bool is_created_by_script,
Dave Tapuska84449382020-05-01 00:39:04191 const base::UnguessableToken& frame_token,
Balazs Engedyba034e72017-10-27 22:26:28192 const base::UnguessableToken& devtools_frame_token,
Luna Luc3fdacdf2017-11-08 04:48:53193 const blink::FramePolicy& frame_policy,
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:54194 const blink::mojom::FrameOwnerProperties& frame_owner_properties,
Ehsan Karamad192a8da2018-10-21 03:48:08195 bool was_discarded,
Antonio Gomes58d38062020-04-30 01:50:14196 blink::mojom::FrameOwnerElementType owner_type) {
nick8814e652015-12-18 01:44:12197 CHECK_NE(new_routing_id, MSG_ROUTING_NONE);
198
dgroganfb22f9a2014-10-20 21:32:32199 // A child frame always starts with an initial empty document, which means
200 // it is in the same SiteInstance as the parent frame. Ensure that the process
201 // which requested a child frame to be added is the same as the process of the
202 // parent node.
Alexander Timin381e7e182020-04-28 19:04:03203 if (parent->GetProcess()->GetID() != process_id)
Lucas Furukawa Gadani99125822019-01-03 15:41:49204 return nullptr;
dgroganfb22f9a2014-10-20 21:32:32205
iclelland098da752017-06-28 13:46:50206 std::unique_ptr<FrameTreeNode> new_node = base::WrapUnique(new FrameTreeNode(
Fergal Daly09d6c762020-05-29 02:05:18207 this, parent, scope, frame_name, frame_unique_name, is_created_by_script,
208 devtools_frame_token, frame_owner_properties, owner_type));
iclelland098da752017-06-28 13:46:50209
210 // Set sandbox flags and container policy and make them effective immediately,
211 // since initial sandbox flags and feature policy should apply to the initial
212 // empty document in the frame. This needs to happen before the call to
213 // AddChild so that the effective policy is sent to any newly-created
214 // RenderFrameProxy objects when the RenderFrameHost is created.
Charlie Hu5ffc0152019-12-06 15:59:53215 // SetPendingFramePolicy is necessary here because next navigation on this
216 // frame will need the value of pending frame policy instead of effective
217 // frame policy.
Ian Clellandcdc4f312017-10-13 22:24:12218 new_node->SetPendingFramePolicy(frame_policy);
Charlie Hu5ffc0152019-12-06 15:59:53219 new_node->CommitFramePolicy(frame_policy);
iclelland098da752017-06-28 13:46:50220
Shubhie Panickerddf2a4e2018-03-06 00:09:06221 if (was_discarded)
222 new_node->set_was_discarded();
223
iclelland098da752017-06-28 13:46:50224 // Add the new node to the FrameTree, creating the RenderFrameHost.
Dave Tapuska84449382020-05-01 00:39:04225 FrameTreeNode* added_node = parent->AddChild(std::move(new_node), process_id,
226 new_routing_id, frame_token);
nick8814e652015-12-18 01:44:12227
Gyuyoung Kim6c9ce9022019-11-26 05:40:08228 DCHECK(interface_provider_receiver.is_valid());
229 added_node->current_frame_host()->BindInterfaceProviderReceiver(
230 std::move(interface_provider_receiver));
Balazs Engedyba034e72017-10-27 22:26:28231
Oksana Zhuravlovafee097c2019-07-26 17:01:30232 DCHECK(browser_interface_broker_receiver.is_valid());
233 added_node->current_frame_host()->BindBrowserInterfaceBrokerReceiver(
234 std::move(browser_interface_broker_receiver));
235
nasko03ecfad2016-08-02 00:54:06236 // The last committed NavigationEntry may have a FrameNavigationEntry with the
237 // same |frame_unique_name|, since we don't remove FrameNavigationEntries if
238 // their frames are deleted. If there is a stale one, remove it to avoid
239 // conflicts on future updates.
Fergal Daly09d6c762020-05-29 02:05:18240 NavigationEntryImpl* last_committed_entry = static_cast<NavigationEntryImpl*>(
241 navigator_.GetController()->GetLastCommittedEntry());
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45242 if (last_committed_entry) {
243 last_committed_entry->RemoveEntryForFrame(
244 added_node, /* only_if_different_position = */ true);
245 }
nasko03ecfad2016-08-02 00:54:06246
nick8814e652015-12-18 01:44:12247 // Now that the new node is part of the FrameTree and has a RenderFrameHost,
248 // we can announce the creation of the initial RenderFrame which already
249 // exists in the renderer process.
Ehsan Karamad44fc72112019-02-26 18:15:47250 if (added_node->frame_owner_element_type() !=
Antonio Gomes58d38062020-04-30 01:50:14251 blink::mojom::FrameOwnerElementType::kPortal) {
Ehsan Karamad44fc72112019-02-26 18:15:47252 // Portals do not have a live RenderFrame in the renderer process.
253 added_node->current_frame_host()->SetRenderFrameCreated(true);
254 }
Lucas Furukawa Gadani99125822019-01-03 15:41:49255 return added_node;
[email protected]9b159a52013-10-03 17:24:55256}
257
[email protected]58faf942014-02-20 21:03:58258void FrameTree::RemoveFrame(FrameTreeNode* child) {
Alexander Timin381e7e182020-04-28 19:04:03259 RenderFrameHostImpl* parent = child->parent();
[email protected]58faf942014-02-20 21:03:58260 if (!parent) {
261 NOTREACHED() << "Unexpected RemoveFrame call for main frame.";
262 return;
[email protected]9b159a52013-10-03 17:24:55263 }
264
Alexander Timin381e7e182020-04-28 19:04:03265 parent->RemoveChild(child);
[email protected]9b159a52013-10-03 17:24:55266}
267
Aran Gilman37d11632019-10-08 23:07:15268void FrameTree::CreateProxiesForSiteInstance(FrameTreeNode* source,
269 SiteInstance* site_instance) {
naskob3041b98a42016-03-12 04:43:06270 // Create the RenderFrameProxyHost for the new SiteInstance.
alexmos58729042015-06-18 23:20:00271 if (!source || !source->IsMainFrame()) {
arthursonzognic5be3842019-07-09 11:49:14272 RenderViewHostImpl* render_view_host =
273 GetRenderViewHost(site_instance).get();
274 if (render_view_host) {
alexmos58729042015-06-18 23:20:00275 root()->render_manager()->EnsureRenderViewInitialized(render_view_host,
276 site_instance);
arthursonzognic5be3842019-07-09 11:49:14277 } else {
278 root()->render_manager()->CreateRenderFrameProxy(site_instance);
[email protected]82307f6b2014-08-07 03:30:12279 }
280 }
281
Alex Moshchuk1226b152019-11-08 18:23:45282 // Check whether we're in an inner delegate and |site_instance| corresponds
283 // to the outer delegate. Subframe proxies aren't needed if this is the
284 // case.
285 bool is_site_instance_for_outer_delegate = false;
286 RenderFrameProxyHost* outer_delegate_proxy =
287 root()->render_manager()->GetProxyToOuterDelegate();
288 if (outer_delegate_proxy) {
289 is_site_instance_for_outer_delegate =
290 (site_instance == outer_delegate_proxy->GetSiteInstance());
291 }
292
naskoe6edde32014-10-17 15:36:48293 // Proxies are created in the FrameTree in response to a node navigating to a
294 // new SiteInstance. Since |source|'s navigation will replace the currently
Alex Moshchuk27caae82017-09-11 23:11:18295 // loaded document, the entire subtree under |source| will be removed, and
296 // thus proxy creation is skipped for all nodes in that subtree.
297 //
298 // However, a proxy *is* needed for the |source| node itself. This lets
299 // cross-process navigations in |source| start with a proxy and follow a
300 // remote-to-local transition, which avoids race conditions in cases where
301 // other navigations need to reference |source| before it commits. See
302 // https://crbug.com/756790 for more background. Therefore,
303 // NodesExceptSubtree(source) will include |source| in the nodes traversed
304 // (see NodeIterator::operator++).
305 for (FrameTreeNode* node : NodesExceptSubtree(source)) {
dcheng57e39e22016-01-21 00:25:38306 // If a new frame is created in the current SiteInstance, other frames in
307 // that SiteInstance don't need a proxy for the new frame.
Alex Moshchuk27caae82017-09-11 23:11:18308 RenderFrameHostImpl* current_host =
309 node->render_manager()->current_frame_host();
310 SiteInstance* current_instance = current_host->GetSiteInstance();
311 if (current_instance != site_instance) {
312 if (node == source && !current_host->IsRenderFrameLive()) {
313 // There's no need to create a proxy at |source| when the current
314 // RenderFrameHost isn't live, as in that case, the pending
315 // RenderFrameHost will be committed immediately, and the proxy
316 // destroyed right away, in GetFrameHostForNavigation. This makes the
317 // race described above not possible.
318 continue;
319 }
Alex Moshchuk1226b152019-11-08 18:23:45320
321 // Do not create proxies for subframes in the outer delegate's
322 // SiteInstance, since there is no need to expose these subframes to the
323 // outer delegate. See also comments in CreateProxiesForChildFrame() and
324 // https://crbug.com/1013553.
325 if (!node->IsMainFrame() && is_site_instance_for_outer_delegate)
326 continue;
327
dcheng57e39e22016-01-21 00:25:38328 node->render_manager()->CreateRenderFrameProxy(site_instance);
Alex Moshchuk27caae82017-09-11 23:11:18329 }
dcheng57e39e22016-01-21 00:25:38330 }
[email protected]82307f6b2014-08-07 03:30:12331}
332
[email protected]9b159a52013-10-03 17:24:55333RenderFrameHostImpl* FrameTree::GetMainFrame() const {
[email protected]94d0cc12013-12-18 00:07:41334 return root_->current_frame_host();
[email protected]9b159a52013-10-03 17:24:55335}
336
[email protected]9c9343b2014-03-08 02:56:07337FrameTreeNode* FrameTree::GetFocusedFrame() {
338 return FindByID(focused_frame_tree_node_id_);
339}
340
alexmos5357efb2015-12-16 21:44:00341void FrameTree::SetFocusedFrame(FrameTreeNode* node, SiteInstance* source) {
342 if (node == GetFocusedFrame())
343 return;
344
dcheng57e39e22016-01-21 00:25:38345 std::set<SiteInstance*> frame_tree_site_instances =
346 CollectSiteInstances(this);
alexmosb1dc2162015-11-05 00:59:20347
alexmos5357efb2015-12-16 21:44:00348 SiteInstance* current_instance =
349 node->current_frame_host()->GetSiteInstance();
350
alexmosb1dc2162015-11-05 00:59:20351 // Update the focused frame in all other SiteInstances. If focus changes to
352 // a cross-process frame, this allows the old focused frame's renderer
353 // process to clear focus from that frame and fire blur events. It also
354 // ensures that the latest focused frame is available in all renderers to
355 // compute document.activeElement.
alexmos5357efb2015-12-16 21:44:00356 //
357 // We do not notify the |source| SiteInstance because it already knows the
358 // new focused frame (since it initiated the focus change), and we notify the
359 // new focused frame's SiteInstance (if it differs from |source|) separately
360 // below.
vmpstr10e0d5f2016-07-21 23:46:09361 for (auto* instance : frame_tree_site_instances) {
alexmos5357efb2015-12-16 21:44:00362 if (instance != source && instance != current_instance) {
alexmosb1dc2162015-11-05 00:59:20363 RenderFrameProxyHost* proxy =
364 node->render_manager()->GetRenderFrameProxyHost(instance);
365 proxy->SetFocusedFrame();
366 }
alexmosca2c6ba2015-10-01 21:52:25367 }
368
alexmos5357efb2015-12-16 21:44:00369 // If |node| was focused from a cross-process frame (i.e., via
370 // window.focus()), tell its RenderFrame that it should focus.
371 if (current_instance != source)
372 node->current_frame_host()->SetFocusedFrame();
373
[email protected]9c9343b2014-03-08 02:56:07374 focused_frame_tree_node_id_ = node->frame_tree_node_id();
alexmos21acae52015-11-07 01:04:43375 node->DidFocus();
dmazzonif27bf892016-03-10 15:51:55376
377 // The accessibility tree data for the root of the frame tree keeps
378 // track of the focused frame too, so update that every time the
379 // focused frame changes.
380 root()->current_frame_host()->UpdateAXTreeData();
[email protected]9c9343b2014-03-08 02:56:07381}
382
[email protected]9b159a52013-10-03 17:24:55383void FrameTree::SetFrameRemoveListener(
danakj1606c572019-11-27 22:34:03384 base::RepeatingCallback<void(RenderFrameHost*)> on_frame_removed) {
385 on_frame_removed_ = std::move(on_frame_removed);
[email protected]9b159a52013-10-03 17:24:55386}
387
arthursonzognic5be3842019-07-09 11:49:14388scoped_refptr<RenderViewHostImpl> FrameTree::CreateRenderViewHost(
avib7348942015-12-25 20:57:10389 SiteInstance* site_instance,
avib7348942015-12-25 20:57:10390 int32_t main_frame_routing_id,
danakj22b4e8b2019-08-01 23:14:39391 bool swapped_out) {
dcheng29f5a6c2015-08-31 21:43:27392 RenderViewHostImpl* rvh =
393 static_cast<RenderViewHostImpl*>(RenderViewHostFactory::Create(
394 site_instance, render_view_delegate_, render_widget_delegate_,
Fergal Dalyfd9136d2020-03-11 14:53:36395 main_frame_routing_id, swapped_out));
Lowell Manners75055a132019-10-11 10:30:29396 RegisterRenderViewHost(rvh);
arthursonzognic5be3842019-07-09 11:49:14397 return base::WrapRefCounted(rvh);
[email protected]94d0cc12013-12-18 00:07:41398}
399
arthursonzognic5be3842019-07-09 11:49:14400scoped_refptr<RenderViewHostImpl> FrameTree::GetRenderViewHost(
401 SiteInstance* site_instance) {
arthursonzogni88e54ae2019-04-15 12:57:36402 auto it = render_view_host_map_.find(site_instance->GetId());
403 if (it == render_view_host_map_.end())
404 return nullptr;
alexmos9aa61232016-04-26 21:54:02405
arthursonzognic5be3842019-07-09 11:49:14406 return base::WrapRefCounted(it->second);
[email protected]94d0cc12013-12-18 00:07:41407}
408
Lowell Manners75055a132019-10-11 10:30:29409void FrameTree::RegisterRenderViewHost(RenderViewHostImpl* rvh) {
410 CHECK(
411 !base::Contains(render_view_host_map_, rvh->GetSiteInstance()->GetId()));
412 render_view_host_map_[rvh->GetSiteInstance()->GetId()] = rvh;
413}
414
415void FrameTree::UnregisterRenderViewHost(RenderViewHostImpl* rvh) {
arthursonzogni88e54ae2019-04-15 12:57:36416 auto it = render_view_host_map_.find(rvh->GetSiteInstance()->GetId());
417 CHECK(it != render_view_host_map_.end());
arthursonzognic5be3842019-07-09 11:49:14418 CHECK_EQ(it->second, rvh);
419 render_view_host_map_.erase(it);
[email protected]94d0cc12013-12-18 00:07:41420}
421
arthursonzogni0a2007792019-05-28 21:32:48422void FrameTree::FrameUnloading(FrameTreeNode* frame) {
423 if (frame->frame_tree_node_id() == focused_frame_tree_node_id_)
424 focused_frame_tree_node_id_ = FrameTreeNode::kFrameTreeNodeInvalidId;
425
426 // Ensure frames that are about to be deleted aren't visible from the other
427 // processes anymore.
428 frame->render_manager()->ResetProxyHosts();
429}
430
dmazzonie950ea232015-03-13 21:39:45431void FrameTree::FrameRemoved(FrameTreeNode* frame) {
nick53d5cbf2015-04-23 22:50:14432 if (frame->frame_tree_node_id() == focused_frame_tree_node_id_)
thestige62f7382016-11-08 18:31:39433 focused_frame_tree_node_id_ = FrameTreeNode::kFrameTreeNodeInvalidId;
nick53d5cbf2015-04-23 22:50:14434
dmazzonie950ea232015-03-13 21:39:45435 // No notification for the root frame.
clamy9dbf17e22015-03-31 13:37:08436 if (!frame->parent()) {
nick70b782d2015-10-06 17:37:04437 CHECK_EQ(frame, root_);
dmazzonie950ea232015-03-13 21:39:45438 return;
clamy9dbf17e22015-03-31 13:37:08439 }
dmazzonie950ea232015-03-13 21:39:45440
441 // Notify observers of the frame removal.
442 if (!on_frame_removed_.is_null())
443 on_frame_removed_.Run(frame->current_frame_host());
444}
445
Nate Chapin93536702018-02-07 00:12:21446void FrameTree::UpdateLoadProgress(double progress) {
fdegansa696e5112015-04-17 01:57:59447 if (progress <= load_progress_)
448 return;
449 load_progress_ = progress;
450
451 // Notify the WebContents.
Fergal Daly09d6c762020-05-29 02:05:18452 root_->navigator().GetDelegate()->DidChangeLoadProgress();
fdegans1d16355162015-03-26 11:58:34453}
454
455void FrameTree::ResetLoadProgress() {
fdegansa696e5112015-04-17 01:57:59456 load_progress_ = 0.0;
fdegans1d16355162015-03-26 11:58:34457}
458
clamy44e84ce2016-02-22 15:38:25459bool FrameTree::IsLoading() const {
nick931d4452016-03-30 00:59:06460 for (const FrameTreeNode* node : const_cast<FrameTree*>(this)->Nodes()) {
dcheng57e39e22016-01-21 00:25:38461 if (node->IsLoading())
462 return true;
463 }
464 return false;
fdegans1d16355162015-03-26 11:58:34465}
466
alexmos3fcd0ca2015-10-23 18:18:33467void FrameTree::ReplicatePageFocus(bool is_focused) {
dcheng57e39e22016-01-21 00:25:38468 std::set<SiteInstance*> frame_tree_site_instances =
469 CollectSiteInstances(this);
alexmos3fcd0ca2015-10-23 18:18:33470
471 // Send the focus update to main frame's proxies in all SiteInstances of
472 // other frames in this FrameTree. Note that the main frame might also know
473 // about proxies in SiteInstances for frames in a different FrameTree (e.g.,
474 // for window.open), so we can't just iterate over its proxy_hosts_ in
475 // RenderFrameHostManager.
vmpstr10e0d5f2016-07-21 23:46:09476 for (auto* instance : frame_tree_site_instances)
alexmos0d7e0b09b2015-10-29 22:11:48477 SetPageFocus(instance, is_focused);
478}
alexmos3fcd0ca2015-10-23 18:18:33479
alexmos0d7e0b09b2015-10-29 22:11:48480void FrameTree::SetPageFocus(SiteInstance* instance, bool is_focused) {
481 RenderFrameHostManager* root_manager = root_->render_manager();
482
483 // This is only used to set page-level focus in cross-process subframes, and
484 // requests to set focus in main frame's SiteInstance are ignored.
485 if (instance != root_manager->current_frame_host()->GetSiteInstance()) {
alexmos3fcd0ca2015-10-23 18:18:33486 RenderFrameProxyHost* proxy =
alexmos0d7e0b09b2015-10-29 22:11:48487 root_manager->GetRenderFrameProxyHost(instance);
Julie Jeongeun Kim2002cb32020-01-17 11:37:29488 proxy->GetAssociatedRemoteFrame()->SetPageFocus(is_focused);
alexmos3fcd0ca2015-10-23 18:18:33489 }
490}
491
W. James MacLeanb70fab82020-05-01 18:51:14492void FrameTree::RegisterExistingOriginToPreventOptInIsolation(
493 const url::Origin& previously_visited_origin,
494 NavigationRequest* navigation_request_to_exclude) {
495 std::unordered_set<SiteInstance*> matching_site_instances;
496
497 // Be sure to visit all RenderFrameHosts associated with this frame that might
498 // have an origin that could script other frames. We skip RenderFrameHosts
499 // that are in the bfcache, assuming there's no way for a frame to join the
500 // BrowsingInstance of a bfcache RFH while it's in the cache.
501 for (auto* frame_tree_node : SubtreeNodes(root())) {
502 auto* frame_host = frame_tree_node->current_frame_host();
503
504 if (previously_visited_origin == frame_host->GetLastCommittedOrigin())
505 matching_site_instances.insert(frame_host->GetSiteInstance());
506
507 if (frame_host->HasCommittingNavigationRequestForOrigin(
508 previously_visited_origin, navigation_request_to_exclude)) {
509 matching_site_instances.insert(frame_host->GetSiteInstance());
510 }
511
512 auto* spec_frame_host =
513 frame_tree_node->render_manager()->speculative_frame_host();
514 if (spec_frame_host &&
515 spec_frame_host->HasCommittingNavigationRequestForOrigin(
516 previously_visited_origin, navigation_request_to_exclude)) {
517 matching_site_instances.insert(spec_frame_host->GetSiteInstance());
518 }
519
520 auto* navigation_request = frame_tree_node->navigation_request();
521 if (navigation_request &&
522 navigation_request != navigation_request_to_exclude &&
523 navigation_request->HasCommittingOrigin(previously_visited_origin)) {
524 matching_site_instances.insert(frame_host->GetSiteInstance());
525 }
526 }
527
528 // Update any SiteInstances found to contain |origin|.
529 for (auto* site_instance : matching_site_instances) {
530 static_cast<SiteInstanceImpl*>(site_instance)
531 ->PreventOptInOriginIsolation(previously_visited_origin);
532 }
533}
534
[email protected]9b159a52013-10-03 17:24:55535} // namespace content