1 // Copyright 2014 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
5 #include "content/renderer/render_frame_proxy.h"
6
7 #include <stdint.h>
8 #include <map>
9 #include <memory>
10 #include <utility>
11
12 #include "base/command_line.h"
13 #include "base/lazy_instance.h"
14 #include "base/memory/ptr_util.h"
15 #include "components/viz/common/surfaces/local_surface_id_allocation.h"
16 #include "content/common/content_switches_internal.h"
17 #include "content/common/frame_replication_state.h"
18 #include "content/common/input_messages.h"
19 #include "content/common/page_messages.h"
20 #include "content/common/unfreezable_frame_messages.h"
21 #include "content/common/view_messages.h"
22 #include "content/public/common/content_client.h"
23 #include "content/public/common/content_switches.h"
24 #include "content/public/common/screen_info.h"
25 #include "content/public/common/use_zoom_for_dsf_policy.h"
26 #include "content/public/renderer/content_renderer_client.h"
27 #include "content/renderer/child_frame_compositing_helper.h"
28 #include "content/renderer/loader/web_url_request_util.h"
29 #include "content/renderer/mojo/blink_interface_registry_impl.h"
30 #include "content/renderer/render_frame_impl.h"
31 #include "content/renderer/render_thread_impl.h"
32 #include "content/renderer/render_view_impl.h"
33 #include "content/renderer/render_widget.h"
34 #include "ipc/ipc_message_macros.h"
35 #include "mojo/public/cpp/bindings/pending_associated_remote.h"
36 #include "printing/buildflags/buildflags.h"
37 #include "third_party/blink/public/common/feature_policy/feature_policy.h"
38 #include "third_party/blink/public/common/frame/frame_policy.h"
39 #include "third_party/blink/public/common/navigation/triggering_event_info.h"
40 #include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom.h"
41 #include "third_party/blink/public/platform/url_conversion.h"
42 #include "third_party/blink/public/platform/web_rect.h"
43 #include "third_party/blink/public/platform/web_string.h"
44 #include "third_party/blink/public/web/web_local_frame.h"
45 #include "third_party/blink/public/web/web_view.h"
46 #include "ui/gfx/geometry/size_conversions.h"
47
48 #if BUILDFLAG(ENABLE_PRINTING)
49 // nogncheck because dependency on //printing is conditional upon
50 // enable_basic_printing flags.
51 #include "printing/metafile_skia.h" // nogncheck
52 #endif
53
54 namespace content {
55
56 namespace {
57
58 // Facilitates lookup of RenderFrameProxy by routing_id.
59 typedef std::map<int, RenderFrameProxy*> RoutingIDProxyMap;
60 static base::LazyInstance<RoutingIDProxyMap>::DestructorAtExit
61 g_routing_id_proxy_map = LAZY_INSTANCE_INITIALIZER;
62
63 // Facilitates lookup of RenderFrameProxy by WebRemoteFrame.
64 typedef std::map<blink::WebRemoteFrame*, RenderFrameProxy*> FrameProxyMap;
65 base::LazyInstance<FrameProxyMap>::DestructorAtExit g_frame_proxy_map =
66 LAZY_INSTANCE_INITIALIZER;
67
68 } // namespace
69
70 // static
CreateProxyToReplaceFrame(RenderFrameImpl * frame_to_replace,int routing_id,blink::WebTreeScopeType scope)71 RenderFrameProxy* RenderFrameProxy::CreateProxyToReplaceFrame(
72 RenderFrameImpl* frame_to_replace,
73 int routing_id,
74 blink::WebTreeScopeType scope) {
75 CHECK_NE(routing_id, MSG_ROUTING_NONE);
76
77 std::unique_ptr<RenderFrameProxy> proxy(new RenderFrameProxy(routing_id));
78 proxy->unique_name_ = frame_to_replace->unique_name();
79 proxy->devtools_frame_token_ = frame_to_replace->GetDevToolsFrameToken();
80
81 // When a RenderFrame is replaced by a RenderProxy, the WebRemoteFrame should
82 // always come from WebRemoteFrame::create and a call to WebFrame::swap must
83 // follow later.
84 blink::WebRemoteFrame* web_frame = blink::WebRemoteFrame::Create(
85 scope, proxy.get(), proxy->blink_interface_registry_.get(),
86 proxy->GetRemoteAssociatedInterfaces());
87
88 RenderWidget* ancestor_widget = nullptr;
89 bool parent_is_local = false;
90
91 // A top level frame proxy doesn't have a RenderWidget pointer. The pointer
92 // is to an ancestor local frame's RenderWidget and there are no ancestors.
93 if (frame_to_replace->GetWebFrame()->Parent()) {
94 if (frame_to_replace->GetWebFrame()->Parent()->IsWebLocalFrame()) {
95 // If the frame was a local frame, get its local root's RenderWidget.
96 ancestor_widget = frame_to_replace->GetLocalRootRenderWidget();
97 parent_is_local = true;
98 } else {
99 // Otherwise, grab the pointer from the parent RenderFrameProxy, as
100 // it would already have the correct pointer. A proxy with a proxy child
101 // must be created before its child, so the first proxy in a descendant
102 // chain is either the root or has a local parent frame.
103 RenderFrameProxy* parent = RenderFrameProxy::FromWebFrame(
104 frame_to_replace->GetWebFrame()->Parent()->ToWebRemoteFrame());
105 ancestor_widget = parent->ancestor_render_widget_;
106 }
107 }
108
109 proxy->Init(web_frame, frame_to_replace->render_view(), ancestor_widget,
110 parent_is_local);
111 return proxy.release();
112 }
113
CreateFrameProxy(int routing_id,int render_view_routing_id,blink::WebFrame * opener,int parent_routing_id,const FrameReplicationState & replicated_state,const base::UnguessableToken & devtools_frame_token)114 RenderFrameProxy* RenderFrameProxy::CreateFrameProxy(
115 int routing_id,
116 int render_view_routing_id,
117 blink::WebFrame* opener,
118 int parent_routing_id,
119 const FrameReplicationState& replicated_state,
120 const base::UnguessableToken& devtools_frame_token) {
121 RenderFrameProxy* parent = nullptr;
122 if (parent_routing_id != MSG_ROUTING_NONE) {
123 parent = RenderFrameProxy::FromRoutingID(parent_routing_id);
124 // It is possible that the parent proxy has been detached in this renderer
125 // process, just as the parent's real frame was creating this child frame.
126 // In this case, do not create the proxy. See https://crbug.com/568670.
127 if (!parent)
128 return nullptr;
129 }
130
131 std::unique_ptr<RenderFrameProxy> proxy(new RenderFrameProxy(routing_id));
132 proxy->devtools_frame_token_ = devtools_frame_token;
133 RenderViewImpl* render_view = nullptr;
134 RenderWidget* ancestor_widget = nullptr;
135 blink::WebRemoteFrame* web_frame = nullptr;
136
137 if (!parent) {
138 // Create a top level WebRemoteFrame.
139 render_view = RenderViewImpl::FromRoutingID(render_view_routing_id);
140 web_frame = blink::WebRemoteFrame::CreateMainFrame(
141 render_view->GetWebView(), proxy.get(),
142 proxy->blink_interface_registry_.get(),
143 proxy->GetRemoteAssociatedInterfaces(), opener);
144 // Root frame proxy has no ancestors to point to their RenderWidget.
145 } else {
146 // Create a frame under an existing parent. The parent is always expected
147 // to be a RenderFrameProxy, because navigations initiated by local frames
148 // should not wind up here.
149 web_frame = parent->web_frame()->CreateRemoteChild(
150 replicated_state.scope,
151 blink::WebString::FromUTF8(replicated_state.name),
152 replicated_state.frame_policy,
153 replicated_state.frame_owner_element_type, proxy.get(),
154 proxy->blink_interface_registry_.get(),
155 proxy->GetRemoteAssociatedInterfaces(), opener);
156 proxy->unique_name_ = replicated_state.unique_name;
157 render_view = parent->render_view();
158 ancestor_widget = parent->ancestor_render_widget_;
159 }
160
161 proxy->Init(web_frame, render_view, ancestor_widget, false);
162
163 // Initialize proxy's WebRemoteFrame with the security origin and other
164 // replicated information.
165 // TODO(dcheng): Calling this when parent_routing_id != MSG_ROUTING_NONE is
166 // mostly redundant, since we already pass the name and sandbox flags in
167 // createLocalChild(). We should update the Blink interface so it also takes
168 // the origin. Then it will be clear that the replication call is only needed
169 // for the case of setting up a main frame proxy.
170 proxy->SetReplicatedState(replicated_state);
171
172 return proxy.release();
173 }
174
CreateProxyForPortal(RenderFrameImpl * parent,int proxy_routing_id,const base::UnguessableToken & devtools_frame_token,const blink::WebElement & portal_element)175 RenderFrameProxy* RenderFrameProxy::CreateProxyForPortal(
176 RenderFrameImpl* parent,
177 int proxy_routing_id,
178 const base::UnguessableToken& devtools_frame_token,
179 const blink::WebElement& portal_element) {
180 auto proxy = base::WrapUnique(new RenderFrameProxy(proxy_routing_id));
181 proxy->devtools_frame_token_ = devtools_frame_token;
182 blink::WebRemoteFrame* web_frame = blink::WebRemoteFrame::CreateForPortal(
183 blink::WebTreeScopeType::kDocument, proxy.get(),
184 proxy->blink_interface_registry_.get(),
185 proxy->GetRemoteAssociatedInterfaces(), portal_element);
186 proxy->Init(web_frame, parent->render_view(),
187 parent->GetLocalRootRenderWidget(), true);
188 return proxy.release();
189 }
190
191 // static
FromRoutingID(int32_t routing_id)192 RenderFrameProxy* RenderFrameProxy::FromRoutingID(int32_t routing_id) {
193 RoutingIDProxyMap* proxies = g_routing_id_proxy_map.Pointer();
194 auto it = proxies->find(routing_id);
195 return it == proxies->end() ? NULL : it->second;
196 }
197
198 // static
FromWebFrame(blink::WebRemoteFrame * web_frame)199 RenderFrameProxy* RenderFrameProxy::FromWebFrame(
200 blink::WebRemoteFrame* web_frame) {
201 // TODO(dcheng): Turn this into a DCHECK() if it doesn't crash on canary.
202 CHECK(web_frame);
203 auto iter = g_frame_proxy_map.Get().find(web_frame);
204 if (iter != g_frame_proxy_map.Get().end()) {
205 RenderFrameProxy* proxy = iter->second;
206 DCHECK_EQ(web_frame, proxy->web_frame());
207 return proxy;
208 }
209 // Reaching this is not expected: this implies that the |web_frame| in
210 // question is not managed by the content API, or the associated
211 // RenderFrameProxy is already deleted--in which case, it's not safe to touch
212 // |web_frame|.
213 NOTREACHED();
214 return nullptr;
215 }
216
RenderFrameProxy(int routing_id)217 RenderFrameProxy::RenderFrameProxy(int routing_id)
218 : routing_id_(routing_id),
219 provisional_frame_routing_id_(MSG_ROUTING_NONE),
220 // TODO(samans): Investigate if it is safe to delay creation of this
221 // object until a FrameSinkId is provided.
222 parent_local_surface_id_allocator_(
223 std::make_unique<viz::ParentLocalSurfaceIdAllocator>()) {
224 std::pair<RoutingIDProxyMap::iterator, bool> result =
225 g_routing_id_proxy_map.Get().insert(std::make_pair(routing_id_, this));
226 CHECK(result.second) << "Inserting a duplicate item.";
227 RenderThread::Get()->AddRoute(routing_id_, this);
228 blink_interface_registry_.reset(new BlinkInterfaceRegistryImpl(
229 binder_registry_.GetWeakPtr(), associated_interfaces_.GetWeakPtr()));
230 }
231
~RenderFrameProxy()232 RenderFrameProxy::~RenderFrameProxy() {
233 if (ancestor_render_widget_)
234 ancestor_render_widget_->UnregisterRenderFrameProxy(this);
235
236 CHECK(!web_frame_);
237 RenderThread::Get()->RemoveRoute(routing_id_);
238 g_routing_id_proxy_map.Get().erase(routing_id_);
239 }
240
Init(blink::WebRemoteFrame * web_frame,RenderViewImpl * render_view,RenderWidget * ancestor_widget,bool parent_is_local)241 void RenderFrameProxy::Init(blink::WebRemoteFrame* web_frame,
242 RenderViewImpl* render_view,
243 RenderWidget* ancestor_widget,
244 bool parent_is_local) {
245 CHECK(web_frame);
246 CHECK(render_view);
247
248 web_frame_ = web_frame;
249 render_view_ = render_view;
250 ancestor_render_widget_ = ancestor_widget;
251
252 // |ancestor_render_widget_| can be null if this is a proxy for a remote main
253 // frame, or a subframe of that proxy. We don't need to register as an
254 // observer [since there is no ancestor RenderWidget]. The observer is used to
255 // propagate VisualProperty changes down the frame/process hierarchy. Remote
256 // main frame proxies do not participate in this flow.
257 if (ancestor_render_widget_) {
258 ancestor_render_widget_->RegisterRenderFrameProxy(this);
259 pending_visual_properties_.screen_info =
260 ancestor_render_widget_->GetOriginalScreenInfo();
261 }
262
263 std::pair<FrameProxyMap::iterator, bool> result =
264 g_frame_proxy_map.Get().insert(std::make_pair(web_frame_, this));
265 CHECK(result.second) << "Inserted a duplicate item.";
266
267 if (parent_is_local)
268 compositing_helper_ = std::make_unique<ChildFrameCompositingHelper>(this);
269 }
270
ResendVisualProperties()271 void RenderFrameProxy::ResendVisualProperties() {
272 // Reset |sent_visual_properties_| in order to allocate a new
273 // viz::LocalSurfaceId.
274 sent_visual_properties_ = base::nullopt;
275 SynchronizeVisualProperties();
276 }
277
OnScreenInfoChanged(const ScreenInfo & screen_info)278 void RenderFrameProxy::OnScreenInfoChanged(const ScreenInfo& screen_info) {
279 DCHECK(ancestor_render_widget_);
280
281 pending_visual_properties_.screen_info = screen_info;
282 if (crashed_) {
283 // Update the sad page to match the current ScreenInfo.
284 compositing_helper_->ChildFrameGone(local_frame_size(),
285 screen_info.device_scale_factor);
286 return;
287 }
288 SynchronizeVisualProperties();
289 }
290
OnZoomLevelChanged(double zoom_level)291 void RenderFrameProxy::OnZoomLevelChanged(double zoom_level) {
292 DCHECK(ancestor_render_widget_);
293
294 pending_visual_properties_.zoom_level = zoom_level;
295 SynchronizeVisualProperties();
296 }
297
OnPageScaleFactorChanged(float page_scale_factor,bool is_pinch_gesture_active)298 void RenderFrameProxy::OnPageScaleFactorChanged(float page_scale_factor,
299 bool is_pinch_gesture_active) {
300 DCHECK(ancestor_render_widget_);
301
302 pending_visual_properties_.page_scale_factor = page_scale_factor;
303 pending_visual_properties_.is_pinch_gesture_active = is_pinch_gesture_active;
304 SynchronizeVisualProperties();
305 }
306
OnVisibleViewportSizeChanged(const gfx::Size & visible_viewport_size)307 void RenderFrameProxy::OnVisibleViewportSizeChanged(
308 const gfx::Size& visible_viewport_size) {
309 DCHECK(ancestor_render_widget_);
310
311 pending_visual_properties_.visible_viewport_size = visible_viewport_size;
312 SynchronizeVisualProperties();
313 }
314
UpdateCaptureSequenceNumber(uint32_t capture_sequence_number)315 void RenderFrameProxy::UpdateCaptureSequenceNumber(
316 uint32_t capture_sequence_number) {
317 DCHECK(ancestor_render_widget_);
318
319 pending_visual_properties_.capture_sequence_number = capture_sequence_number;
320 SynchronizeVisualProperties();
321 }
322
SetReplicatedState(const FrameReplicationState & state)323 void RenderFrameProxy::SetReplicatedState(const FrameReplicationState& state) {
324 DCHECK(web_frame_);
325
326 web_frame_->SetReplicatedOrigin(
327 state.origin, state.has_potentially_trustworthy_unique_origin);
328
329 #if DCHECK_IS_ON()
330 blink::WebSecurityOrigin security_origin_before_sandbox_flags =
331 web_frame_->GetSecurityOrigin();
332 #endif
333
334 web_frame_->SetReplicatedSandboxFlags(state.active_sandbox_flags);
335
336 #if DCHECK_IS_ON()
337 // If |state.has_potentially_trustworthy_unique_origin| is set,
338 // - |state.origin| should be unique (this is checked in
339 // blink::SecurityOrigin::SetUniqueOriginIsPotentiallyTrustworthy() in
340 // SetReplicatedOrigin()), and thus
341 // - The security origin is not updated by SetReplicatedSandboxFlags() and
342 // thus we don't have to apply |has_potentially_trustworthy_unique_origin|
343 // flag after SetReplicatedSandboxFlags().
344 if (state.has_potentially_trustworthy_unique_origin)
345 DCHECK(security_origin_before_sandbox_flags ==
346 web_frame_->GetSecurityOrigin());
347 #endif
348
349 web_frame_->SetReplicatedName(blink::WebString::FromUTF8(state.name));
350 web_frame_->SetReplicatedInsecureRequestPolicy(state.insecure_request_policy);
351 web_frame_->SetReplicatedInsecureNavigationsSet(
352 state.insecure_navigations_set);
353 web_frame_->SetReplicatedAdFrameType(state.ad_frame_type);
354 web_frame_->SetReplicatedFeaturePolicyHeaderAndOpenerPolicies(
355 state.feature_policy_header, state.opener_feature_state);
356 if (state.has_received_user_gesture) {
357 web_frame_->UpdateUserActivationState(
358 blink::mojom::UserActivationUpdateType::kNotifyActivation);
359 }
360 web_frame_->SetHadStickyUserActivationBeforeNavigation(
361 state.has_received_user_gesture_before_nav);
362
363 web_frame_->ResetReplicatedContentSecurityPolicy();
364 for (const auto& header : state.accumulated_csp_headers) {
365 web_frame_->AddReplicatedContentSecurityPolicyHeader(
366 blink::WebString::FromUTF8(header.header_value), header.type,
367 header.source);
368 }
369 }
370
OnMessageReceived(const IPC::Message & msg)371 bool RenderFrameProxy::OnMessageReceived(const IPC::Message& msg) {
372 // Page IPCs are routed via the main frame (both local and remote) and then
373 // forwarded to the RenderView. See comment in
374 // RenderFrameHostManager::SendPageMessage() for more information.
375 if ((IPC_MESSAGE_CLASS(msg) == PageMsgStart)) {
376 if (render_view())
377 return render_view()->OnMessageReceived(msg);
378
379 return false;
380 }
381
382 bool handled = true;
383 IPC_BEGIN_MESSAGE_MAP(RenderFrameProxy, msg)
384 IPC_MESSAGE_HANDLER(FrameMsg_UpdateOpener, OnUpdateOpener)
385 IPC_MESSAGE_HANDLER(FrameMsg_DidUpdateName, OnDidUpdateName)
386 IPC_MESSAGE_HANDLER(FrameMsg_TransferUserActivationFrom,
387 OnTransferUserActivationFrom)
388 IPC_MESSAGE_HANDLER(UnfreezableFrameMsg_DeleteProxy, OnDeleteProxy)
389 IPC_MESSAGE_UNHANDLED(handled = false)
390 IPC_END_MESSAGE_MAP()
391
392 // Note: If |handled| is true, |this| may have been deleted.
393 return handled;
394 }
395
OnAssociatedInterfaceRequest(const std::string & interface_name,mojo::ScopedInterfaceEndpointHandle handle)396 void RenderFrameProxy::OnAssociatedInterfaceRequest(
397 const std::string& interface_name,
398 mojo::ScopedInterfaceEndpointHandle handle) {
399 if (interface_name == blink::mojom::RemoteFrame::Name_) {
400 associated_interfaces_.TryBindInterface(interface_name, &handle);
401 } else if (interface_name == content::mojom::RenderFrameProxy::Name_) {
402 render_frame_proxy_receiver_.Bind(
403 mojo::PendingAssociatedReceiver<mojom::RenderFrameProxy>(
404 std::move(handle)));
405 }
406 }
407
Send(IPC::Message * message)408 bool RenderFrameProxy::Send(IPC::Message* message) {
409 return RenderThread::Get()->Send(message);
410 }
411
OnDeleteProxy()412 void RenderFrameProxy::OnDeleteProxy() {
413 DCHECK(web_frame_);
414 web_frame_->Detach();
415 }
416
ChildProcessGone()417 void RenderFrameProxy::ChildProcessGone() {
418 crashed_ = true;
419 compositing_helper_->ChildFrameGone(local_frame_size(),
420 screen_info().device_scale_factor);
421 }
422
OnUpdateOpener(int opener_routing_id)423 void RenderFrameProxy::OnUpdateOpener(int opener_routing_id) {
424 blink::WebFrame* opener = RenderFrameImpl::ResolveWebFrame(opener_routing_id);
425 web_frame_->SetOpener(opener);
426 }
427
DidStartLoading()428 void RenderFrameProxy::DidStartLoading() {
429 web_frame_->DidStartLoading();
430 }
431
OnDidUpdateName(const std::string & name,const std::string & unique_name)432 void RenderFrameProxy::OnDidUpdateName(const std::string& name,
433 const std::string& unique_name) {
434 web_frame_->SetReplicatedName(blink::WebString::FromUTF8(name));
435 unique_name_ = unique_name;
436 }
437
OnTransferUserActivationFrom(int32_t source_routing_id)438 void RenderFrameProxy::OnTransferUserActivationFrom(int32_t source_routing_id) {
439 RenderFrameProxy* source_proxy =
440 RenderFrameProxy::FromRoutingID(source_routing_id);
441 if (!source_proxy)
442 return;
443 web_frame()->TransferUserActivationFrom(source_proxy->web_frame());
444 }
445
DidUpdateVisualProperties(const cc::RenderFrameMetadata & metadata)446 void RenderFrameProxy::DidUpdateVisualProperties(
447 const cc::RenderFrameMetadata& metadata) {
448 if (!parent_local_surface_id_allocator_->UpdateFromChild(
449 metadata.local_surface_id_allocation.value_or(
450 viz::LocalSurfaceIdAllocation()))) {
451 return;
452 }
453
454 // The viz::LocalSurfaceId has changed so we call SynchronizeVisualProperties
455 // here to embed it.
456 SynchronizeVisualProperties();
457 }
458
EnableAutoResize(const gfx::Size & min_size,const gfx::Size & max_size)459 void RenderFrameProxy::EnableAutoResize(const gfx::Size& min_size,
460 const gfx::Size& max_size) {
461 DCHECK(ancestor_render_widget_);
462
463 pending_visual_properties_.auto_resize_enabled = true;
464 pending_visual_properties_.min_size_for_auto_resize = min_size;
465 pending_visual_properties_.max_size_for_auto_resize = max_size;
466 SynchronizeVisualProperties();
467 }
468
DisableAutoResize()469 void RenderFrameProxy::DisableAutoResize() {
470 DCHECK(ancestor_render_widget_);
471
472 pending_visual_properties_.auto_resize_enabled = false;
473 SynchronizeVisualProperties();
474 }
475
SetFrameSinkId(const viz::FrameSinkId & frame_sink_id)476 void RenderFrameProxy::SetFrameSinkId(const viz::FrameSinkId& frame_sink_id) {
477 FrameSinkIdChanged(frame_sink_id);
478 }
479
SynchronizeVisualProperties()480 void RenderFrameProxy::SynchronizeVisualProperties() {
481 DCHECK(ancestor_render_widget_);
482
483 if (!frame_sink_id_.is_valid() || crashed_)
484 return;
485
486 // Note that the following flag is true if the capture sequence number
487 // actually changed. That is, it is false if we did not have
488 // |sent_visual_properties_|, which is different from
489 // |synchronized_props_changed| below.
490 bool capture_sequence_number_changed =
491 sent_visual_properties_ &&
492 sent_visual_properties_->capture_sequence_number !=
493 pending_visual_properties_.capture_sequence_number;
494
495 if (web_frame_) {
496 pending_visual_properties_.compositor_viewport =
497 web_frame_->GetCompositingRect();
498 }
499
500 bool synchronized_props_changed =
501 !sent_visual_properties_ ||
502 sent_visual_properties_->auto_resize_enabled !=
503 pending_visual_properties_.auto_resize_enabled ||
504 sent_visual_properties_->min_size_for_auto_resize !=
505 pending_visual_properties_.min_size_for_auto_resize ||
506 sent_visual_properties_->max_size_for_auto_resize !=
507 pending_visual_properties_.max_size_for_auto_resize ||
508 sent_visual_properties_->local_frame_size !=
509 pending_visual_properties_.local_frame_size ||
510 sent_visual_properties_->screen_space_rect.size() !=
511 pending_visual_properties_.screen_space_rect.size() ||
512 sent_visual_properties_->screen_info !=
513 pending_visual_properties_.screen_info ||
514 sent_visual_properties_->zoom_level !=
515 pending_visual_properties_.zoom_level ||
516 sent_visual_properties_->page_scale_factor !=
517 pending_visual_properties_.page_scale_factor ||
518 sent_visual_properties_->is_pinch_gesture_active !=
519 pending_visual_properties_.is_pinch_gesture_active ||
520 sent_visual_properties_->visible_viewport_size !=
521 pending_visual_properties_.visible_viewport_size ||
522 sent_visual_properties_->compositor_viewport !=
523 pending_visual_properties_.compositor_viewport ||
524 capture_sequence_number_changed;
525
526 if (synchronized_props_changed) {
527 parent_local_surface_id_allocator_->GenerateId();
528 pending_visual_properties_.local_surface_id_allocation =
529 parent_local_surface_id_allocator_
530 ->GetCurrentLocalSurfaceIdAllocation();
531 }
532
533 // If we're synchronizing surfaces, then use an infinite deadline to ensure
534 // everything is synchronized.
535 cc::DeadlinePolicy deadline = capture_sequence_number_changed
536 ? cc::DeadlinePolicy::UseInfiniteDeadline()
537 : cc::DeadlinePolicy::UseDefaultDeadline();
538 viz::SurfaceId surface_id(frame_sink_id_, GetLocalSurfaceId());
539 compositing_helper_->SetSurfaceId(
540 surface_id, pending_visual_properties_.compositor_viewport.size(),
541 deadline);
542
543 bool rect_changed = !sent_visual_properties_ ||
544 sent_visual_properties_->screen_space_rect !=
545 pending_visual_properties_.screen_space_rect;
546 bool visual_properties_changed = synchronized_props_changed || rect_changed;
547
548 if (!visual_properties_changed)
549 return;
550
551 // Let the browser know about the updated view rect.
552 Send(new FrameHostMsg_SynchronizeVisualProperties(
553 routing_id_, frame_sink_id_, pending_visual_properties_));
554 sent_visual_properties_ = pending_visual_properties_;
555
556 TRACE_EVENT_WITH_FLOW2(
557 TRACE_DISABLED_BY_DEFAULT("viz.surface_id_flow"),
558 "RenderFrameProxy::SynchronizeVisualProperties Send Message",
559 TRACE_ID_GLOBAL(pending_visual_properties_.local_surface_id_allocation
560 .local_surface_id()
561 .submission_trace_id()),
562 TRACE_EVENT_FLAG_FLOW_OUT, "message",
563 "FrameHostMsg_SynchronizeVisualProperties", "local_surface_id",
564 pending_visual_properties_.local_surface_id_allocation.local_surface_id()
565 .ToString());
566 }
567
FrameDetached(DetachType type)568 void RenderFrameProxy::FrameDetached(DetachType type) {
569 if (type == DetachType::kRemove) {
570 // Let the browser process know this subframe is removed, so that it is
571 // destroyed in its current process.
572 Send(new FrameHostMsg_Detach(routing_id_));
573 }
574
575 web_frame_->Close();
576
577 // If this proxy was associated with a provisional RenderFrame, and we're not
578 // in the process of swapping with it, clean it up as well.
579 if (type == DetachType::kRemove &&
580 provisional_frame_routing_id_ != MSG_ROUTING_NONE) {
581 RenderFrameImpl* provisional_frame =
582 RenderFrameImpl::FromRoutingID(provisional_frame_routing_id_);
583 // |provisional_frame| should always exist. If it was deleted via
584 // FrameMsg_Delete right before this proxy was removed,
585 // RenderFrameImpl::frameDetached would've cleared this proxy's
586 // |provisional_frame_routing_id_| and we wouldn't get here.
587 CHECK(provisional_frame);
588 provisional_frame->GetWebFrame()->Detach();
589 }
590
591 // Remove the entry in the WebFrame->RenderFrameProxy map, as the |web_frame_|
592 // is no longer valid.
593 auto it = g_frame_proxy_map.Get().find(web_frame_);
594 CHECK(it != g_frame_proxy_map.Get().end());
595 CHECK_EQ(it->second, this);
596 g_frame_proxy_map.Get().erase(it);
597
598 web_frame_ = nullptr;
599
600 delete this;
601 }
602
ForwardPostMessage(blink::WebLocalFrame * source_frame,blink::WebRemoteFrame * target_frame,blink::WebSecurityOrigin target_origin,blink::WebDOMMessageEvent event)603 void RenderFrameProxy::ForwardPostMessage(
604 blink::WebLocalFrame* source_frame,
605 blink::WebRemoteFrame* target_frame,
606 blink::WebSecurityOrigin target_origin,
607 blink::WebDOMMessageEvent event) {
608 DCHECK(!web_frame_ || web_frame_ == target_frame);
609
610 FrameMsg_PostMessage_Params params;
611 params.message =
612 new base::RefCountedData<blink::TransferableMessage>(event.AsMessage());
613 params.source_origin = event.Origin().Utf16();
614 if (!target_origin.IsNull())
615 params.target_origin = target_origin.ToString().Utf16();
616
617 // Include the routing ID for the source frame (if one exists), which the
618 // browser process will translate into the routing ID for the equivalent
619 // frame in the target process.
620 params.source_routing_id = MSG_ROUTING_NONE;
621 if (source_frame) {
622 RenderFrameImpl* source_render_frame =
623 RenderFrameImpl::FromWebFrame(source_frame);
624 if (source_render_frame)
625 params.source_routing_id = source_render_frame->GetRoutingID();
626 }
627
628 Send(new FrameHostMsg_RouteMessageEvent(routing_id_, params));
629 }
630
Navigate(const blink::WebURLRequest & request,bool should_replace_current_entry,bool is_opener_navigation,bool initiator_frame_has_download_sandbox_flag,bool blocking_downloads_in_sandbox_enabled,bool initiator_frame_is_ad,mojo::ScopedMessagePipeHandle blob_url_token)631 void RenderFrameProxy::Navigate(const blink::WebURLRequest& request,
632 bool should_replace_current_entry,
633 bool is_opener_navigation,
634 bool initiator_frame_has_download_sandbox_flag,
635 bool blocking_downloads_in_sandbox_enabled,
636 bool initiator_frame_is_ad,
637 mojo::ScopedMessagePipeHandle blob_url_token) {
638 // The request must always have a valid initiator origin.
639 DCHECK(!request.RequestorOrigin().IsNull());
640
641 FrameHostMsg_OpenURL_Params params;
642 params.url = request.Url();
643 params.initiator_origin = request.RequestorOrigin();
644 params.post_body = GetRequestBodyForWebURLRequest(request);
645 DCHECK_EQ(!!params.post_body, request.HttpMethod().Utf8() == "POST");
646 params.extra_headers = GetWebURLRequestHeadersAsString(request);
647 params.referrer.url = blink::WebStringToGURL(request.ReferrerString());
648 params.referrer.policy = request.GetReferrerPolicy();
649 params.disposition = WindowOpenDisposition::CURRENT_TAB;
650 params.should_replace_current_entry = should_replace_current_entry;
651 params.user_gesture = request.HasUserGesture();
652 params.triggering_event_info = blink::TriggeringEventInfo::kUnknown;
653 params.blob_url_token = blob_url_token.release();
654
655 // Note: For the AdFrame/Sandbox download policy here it only covers the case
656 // where the navigation initiator frame is ad. The download_policy may be
657 // further augmented in RenderFrameProxyHost::OnOpenURL if the navigating
658 // frame is ad or sandboxed.
659 RenderFrameImpl::MaybeSetDownloadFramePolicy(
660 is_opener_navigation, request, web_frame_->GetSecurityOrigin(),
661 initiator_frame_has_download_sandbox_flag,
662 blocking_downloads_in_sandbox_enabled, initiator_frame_is_ad,
663 ¶ms.download_policy);
664
665 Send(new FrameHostMsg_OpenURL(routing_id_, params));
666 }
667
FrameRectsChanged(const blink::WebRect & local_frame_rect,const blink::WebRect & screen_space_rect)668 void RenderFrameProxy::FrameRectsChanged(
669 const blink::WebRect& local_frame_rect,
670 const blink::WebRect& screen_space_rect) {
671 DCHECK(ancestor_render_widget_);
672
673 pending_visual_properties_.screen_space_rect = gfx::Rect(screen_space_rect);
674 pending_visual_properties_.local_frame_size =
675 gfx::Size(local_frame_rect.width, local_frame_rect.height);
676 pending_visual_properties_.screen_info =
677 ancestor_render_widget_->GetOriginalScreenInfo();
678 if (crashed_) {
679 // Update the sad page to match the current size.
680 compositing_helper_->ChildFrameGone(local_frame_size(),
681 screen_info().device_scale_factor);
682 return;
683 }
684 SynchronizeVisualProperties();
685 }
686
UpdateRemoteViewportIntersection(const blink::ViewportIntersectionState & intersection_state)687 void RenderFrameProxy::UpdateRemoteViewportIntersection(
688 const blink::ViewportIntersectionState& intersection_state) {
689 DCHECK(ancestor_render_widget_);
690 // TODO(szager): compositor_viewport is propagated twice, via
691 // ViewportIntersectionState and also via FrameVisualProperties. It should
692 // only go through FrameVisualProperties.
693 if (pending_visual_properties_.compositor_viewport !=
694 gfx::Rect(intersection_state.compositor_visible_rect)) {
695 SynchronizeVisualProperties();
696 }
697 Send(new FrameHostMsg_UpdateViewportIntersection(routing_id_,
698 intersection_state));
699 }
700
DidChangeOpener(blink::WebFrame * opener)701 void RenderFrameProxy::DidChangeOpener(blink::WebFrame* opener) {
702 // A proxy shouldn't normally be disowning its opener. It is possible to get
703 // here when a proxy that is being detached clears its opener, in which case
704 // there is no need to notify the browser process.
705 if (!opener)
706 return;
707
708 // Only a LocalFrame (i.e., the caller of window.open) should be able to
709 // update another frame's opener.
710 DCHECK(opener->IsWebLocalFrame());
711
712 int opener_routing_id =
713 RenderFrameImpl::FromWebFrame(opener->ToWebLocalFrame())->GetRoutingID();
714 Send(new FrameHostMsg_DidChangeOpener(routing_id_, opener_routing_id));
715 }
716
AdvanceFocus(blink::mojom::FocusType type,blink::WebLocalFrame * source)717 void RenderFrameProxy::AdvanceFocus(blink::mojom::FocusType type,
718 blink::WebLocalFrame* source) {
719 int source_routing_id = RenderFrameImpl::FromWebFrame(source)->GetRoutingID();
720 Send(new FrameHostMsg_AdvanceFocus(routing_id_, type, source_routing_id));
721 }
722
GetDevToolsFrameToken()723 base::UnguessableToken RenderFrameProxy::GetDevToolsFrameToken() {
724 return devtools_frame_token_;
725 }
726
GetLayer()727 cc::Layer* RenderFrameProxy::GetLayer() {
728 return embedded_layer_.get();
729 }
730
SetLayer(scoped_refptr<cc::Layer> layer,bool prevent_contents_opaque_changes,bool is_surface_layer)731 void RenderFrameProxy::SetLayer(scoped_refptr<cc::Layer> layer,
732 bool prevent_contents_opaque_changes,
733 bool is_surface_layer) {
734 if (web_frame()) {
735 web_frame()->SetCcLayer(layer.get(), prevent_contents_opaque_changes,
736 is_surface_layer);
737 }
738 embedded_layer_ = std::move(layer);
739 }
740
GetSadPageBitmap()741 SkBitmap* RenderFrameProxy::GetSadPageBitmap() {
742 return GetContentClient()->renderer()->GetSadWebViewBitmap();
743 }
744
Print(const blink::WebRect & rect,cc::PaintCanvas * canvas)745 uint32_t RenderFrameProxy::Print(const blink::WebRect& rect,
746 cc::PaintCanvas* canvas) {
747 #if BUILDFLAG(ENABLE_PRINTING)
748 auto* metafile = canvas->GetPrintingMetafile();
749 DCHECK(metafile);
750
751 // Create a place holder content for the remote frame so it can be replaced
752 // with actual content later.
753 uint32_t content_id =
754 metafile->CreateContentForRemoteFrame(rect, routing_id_);
755
756 // Inform browser to print the remote subframe.
757 Send(new FrameHostMsg_PrintCrossProcessSubframe(
758 routing_id_, rect, metafile->GetDocumentCookie()));
759 return content_id;
760 #else
761 return 0;
762 #endif
763 }
764
GetLocalSurfaceId() const765 const viz::LocalSurfaceId& RenderFrameProxy::GetLocalSurfaceId() const {
766 return parent_local_surface_id_allocator_
767 ->GetCurrentLocalSurfaceIdAllocation()
768 .local_surface_id();
769 }
770
GetFrameProxyHost()771 mojom::RenderFrameProxyHost* RenderFrameProxy::GetFrameProxyHost() {
772 if (!frame_proxy_host_remote_.is_bound())
773 GetRemoteAssociatedInterfaces()->GetInterface(&frame_proxy_host_remote_);
774 return frame_proxy_host_remote_.get();
775 }
776
777 blink::AssociatedInterfaceProvider*
GetRemoteAssociatedInterfaces()778 RenderFrameProxy::GetRemoteAssociatedInterfaces() {
779 if (!remote_associated_interfaces_) {
780 ChildThreadImpl* thread = ChildThreadImpl::current();
781 if (thread) {
782 mojo::PendingAssociatedRemote<blink::mojom::AssociatedInterfaceProvider>
783 remote_interfaces;
784 thread->GetRemoteRouteProvider()->GetRoute(
785 routing_id_, remote_interfaces.InitWithNewEndpointAndPassReceiver());
786 remote_associated_interfaces_ =
787 std::make_unique<blink::AssociatedInterfaceProvider>(
788 std::move(remote_interfaces));
789 } else {
790 // In some tests the thread may be null,
791 // so set up a self-contained interface provider instead.
792 remote_associated_interfaces_ =
793 std::make_unique<blink::AssociatedInterfaceProvider>(nullptr);
794 }
795 }
796 return remote_associated_interfaces_.get();
797 }
798
WasEvicted()799 void RenderFrameProxy::WasEvicted() {
800 // On eviction, the last SurfaceId is invalidated. We need to allocate a new
801 // id.
802 ResendVisualProperties();
803 }
804
FrameSinkIdChanged(const viz::FrameSinkId & frame_sink_id)805 void RenderFrameProxy::FrameSinkIdChanged(
806 const viz::FrameSinkId& frame_sink_id) {
807 crashed_ = false;
808 // The same ParentLocalSurfaceIdAllocator cannot provide LocalSurfaceIds for
809 // two different frame sinks, so recreate it here.
810 if (frame_sink_id_ != frame_sink_id) {
811 parent_local_surface_id_allocator_ =
812 std::make_unique<viz::ParentLocalSurfaceIdAllocator>();
813 }
814 frame_sink_id_ = frame_sink_id;
815
816 // Resend the FrameRects and allocate a new viz::LocalSurfaceId when the view
817 // changes.
818 ResendVisualProperties();
819 }
820
821 } // namespace content
822