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 "third_party/blink/renderer/core/frame/remote_frame.h"
6
7 #include "cc/layers/surface_layer.h"
8 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
9 #include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-blink.h"
10 #include "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom-blink.h"
11 #include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
12 #include "third_party/blink/public/platform/interface_registry.h"
13 #include "third_party/blink/public/web/web_frame.h"
14 #include "third_party/blink/public/web/web_view.h"
15 #include "third_party/blink/renderer/bindings/core/v8/v8_fullscreen_options.h"
16 #include "third_party/blink/renderer/bindings/core/v8/window_proxy.h"
17 #include "third_party/blink/renderer/bindings/core/v8/window_proxy_manager.h"
18 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
19 #include "third_party/blink/renderer/core/frame/local_frame.h"
20 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
21 #include "third_party/blink/renderer/core/frame/remote_dom_window.h"
22 #include "third_party/blink/renderer/core/frame/remote_frame_client.h"
23 #include "third_party/blink/renderer/core/frame/remote_frame_owner.h"
24 #include "third_party/blink/renderer/core/frame/remote_frame_view.h"
25 #include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
26 #include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
27 #include "third_party/blink/renderer/core/inspector/console_message.h"
28 #include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
29 #include "third_party/blink/renderer/core/layout/intrinsic_sizing_info.h"
30 #include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
31 #include "third_party/blink/renderer/core/layout/layout_view.h"
32 #include "third_party/blink/renderer/core/loader/frame_load_request.h"
33 #include "third_party/blink/renderer/core/loader/frame_loader.h"
34 #include "third_party/blink/renderer/core/loader/mixed_content_checker.h"
35 #include "third_party/blink/renderer/core/page/page.h"
36 #include "third_party/blink/renderer/core/page/plugin_script_forbidden_scope.h"
37 #include "third_party/blink/renderer/core/paint/paint_layer.h"
38 #include "third_party/blink/renderer/core/probe/core_probes.h"
39 #include "third_party/blink/renderer/core/timing/dom_window_performance.h"
40 #include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
41 #include "third_party/blink/renderer/platform/heap/heap.h"
42 #include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h"
43 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
44 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h"
45 #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
46 #include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
47 #include "third_party/blink/renderer/platform/weborigin/security_policy.h"
48
49 namespace blink {
50
51 namespace {
DeNormalizeRect(const gfx::RectF & normalized,const IntRect & base)52 FloatRect DeNormalizeRect(const gfx::RectF& normalized, const IntRect& base) {
53 FloatRect result(normalized);
54 result.Scale(base.Width(), base.Height());
55 result.MoveBy(FloatPoint(base.Location()));
56 return result;
57 }
58
59 } // namespace
60
RemoteFrame(RemoteFrameClient * client,Page & page,FrameOwner * owner,WindowAgentFactory * inheriting_agent_factory,InterfaceRegistry * interface_registry,AssociatedInterfaceProvider * associated_interface_provider)61 RemoteFrame::RemoteFrame(
62 RemoteFrameClient* client,
63 Page& page,
64 FrameOwner* owner,
65 WindowAgentFactory* inheriting_agent_factory,
66 InterfaceRegistry* interface_registry,
67 AssociatedInterfaceProvider* associated_interface_provider)
68 : Frame(client,
69 page,
70 owner,
71 MakeGarbageCollected<RemoteWindowProxyManager>(*this),
72 inheriting_agent_factory) {
73 dom_window_ = MakeGarbageCollected<RemoteDOMWindow>(*this);
74
75 interface_registry->AddAssociatedInterface(WTF::BindRepeating(
76 &RemoteFrame::BindToReceiver, WrapWeakPersistent(this)));
77
78 associated_interface_provider->GetInterface(
79 remote_frame_host_remote_.BindNewEndpointAndPassReceiver());
80
81 UpdateInertIfPossible();
82 UpdateInheritedEffectiveTouchActionIfPossible();
83 UpdateVisibleToHitTesting();
84 Initialize();
85 }
86
~RemoteFrame()87 RemoteFrame::~RemoteFrame() {
88 DCHECK(!view_);
89 }
90
Trace(Visitor * visitor)91 void RemoteFrame::Trace(Visitor* visitor) {
92 visitor->Trace(view_);
93 visitor->Trace(security_context_);
94 Frame::Trace(visitor);
95 }
96
Navigate(FrameLoadRequest & frame_request,WebFrameLoadType frame_load_type)97 void RemoteFrame::Navigate(FrameLoadRequest& frame_request,
98 WebFrameLoadType frame_load_type) {
99 if (!navigation_rate_limiter().CanProceed())
100 return;
101
102 frame_request.SetFrameType(IsMainFrame()
103 ? mojom::RequestContextFrameType::kTopLevel
104 : mojom::RequestContextFrameType::kNested);
105
106 const KURL& url = frame_request.GetResourceRequest().Url();
107 if (!frame_request.CanDisplay(url)) {
108 if (frame_request.OriginDocument()) {
109 frame_request.OriginDocument()->AddConsoleMessage(
110 MakeGarbageCollected<ConsoleMessage>(
111 mojom::ConsoleMessageSource::kSecurity,
112 mojom::ConsoleMessageLevel::kError,
113 "Not allowed to load local resource: " + url.ElidedString()));
114 }
115 return;
116 }
117
118 // The process where this frame actually lives won't have sufficient
119 // information to upgrade the url, since it won't have access to the
120 // originDocument. Do it now.
121 const FetchClientSettingsObject* fetch_client_settings_object = nullptr;
122 if (frame_request.OriginDocument()) {
123 fetch_client_settings_object = &frame_request.OriginDocument()
124 ->Fetcher()
125 ->GetProperties()
126 .GetFetchClientSettingsObject();
127 }
128 LocalFrame* frame = frame_request.OriginDocument()
129 ? frame_request.OriginDocument()->GetFrame()
130 : nullptr;
131 MixedContentChecker::UpgradeInsecureRequest(
132 frame_request.GetResourceRequest(), fetch_client_settings_object,
133 frame_request.OriginDocument()
134 ? frame_request.OriginDocument()->ToExecutionContext()
135 : nullptr,
136 frame_request.GetFrameType(),
137 frame ? frame->GetContentSettingsClient() : nullptr);
138
139 // Navigations in portal contexts do not create back/forward entries.
140 if (GetPage()->InsidePortal() &&
141 frame_load_type == WebFrameLoadType::kStandard) {
142 frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
143 }
144
145 bool is_opener_navigation = false;
146 bool initiator_frame_has_download_sandbox_flag = false;
147 bool initiator_frame_is_ad = false;
148
149 if (frame) {
150 is_opener_navigation = frame->Client()->Opener() == this;
151 initiator_frame_has_download_sandbox_flag =
152 frame->GetSecurityContext() &&
153 frame->GetSecurityContext()->IsSandboxed(
154 mojom::blink::WebSandboxFlags::kDownloads);
155 initiator_frame_is_ad = frame->IsAdSubframe();
156 if (frame_request.ClientRedirectReason() != ClientNavigationReason::kNone) {
157 probe::FrameRequestedNavigation(frame, this, url,
158 frame_request.ClientRedirectReason());
159 }
160 }
161
162 Client()->Navigate(frame_request.GetResourceRequest(),
163 frame_load_type == WebFrameLoadType::kReplaceCurrentItem,
164 is_opener_navigation,
165 initiator_frame_has_download_sandbox_flag,
166 initiator_frame_is_ad, frame_request.GetBlobURLToken());
167 }
168
DetachImpl(FrameDetachType type)169 void RemoteFrame::DetachImpl(FrameDetachType type) {
170 PluginScriptForbiddenScope forbid_plugin_destructor_scripting;
171 DetachChildren();
172 if (!Client())
173 return;
174
175 // Clean up the frame's view if needed. A remote frame only has a view if
176 // the parent is a local frame.
177 if (view_)
178 view_->Dispose();
179 GetWindowProxyManager()->ClearForClose();
180 SetView(nullptr);
181 // ... the RemoteDOMWindow will need to be informed of detachment,
182 // as otherwise it will keep a strong reference back to this RemoteFrame.
183 // That combined with wrappers (owned and kept alive by RemoteFrame) keeping
184 // persistent strong references to RemoteDOMWindow will prevent the GCing
185 // of all these objects. Break the cycle by notifying of detachment.
186 To<RemoteDOMWindow>(dom_window_.Get())->FrameDetached();
187 if (cc_layer_)
188 SetCcLayer(nullptr, false, false);
189 receiver_.reset();
190 }
191
DetachDocument()192 bool RemoteFrame::DetachDocument() {
193 DetachChildren();
194 return !!GetPage();
195 }
196
CheckCompleted()197 void RemoteFrame::CheckCompleted() {
198 // Notify the client so that the corresponding LocalFrame can do the check.
199 GetRemoteFrameHostRemote().CheckCompleted();
200 }
201
GetSecurityContext() const202 const RemoteSecurityContext* RemoteFrame::GetSecurityContext() const {
203 return &security_context_;
204 }
205
ShouldClose()206 bool RemoteFrame::ShouldClose() {
207 // TODO(nasko): Implement running the beforeunload handler in the actual
208 // LocalFrame running in a different process and getting back a real result.
209 return true;
210 }
211
SetIsInert(bool inert)212 void RemoteFrame::SetIsInert(bool inert) {
213 if (inert != is_inert_)
214 GetRemoteFrameHostRemote().SetIsInert(inert);
215 is_inert_ = inert;
216 }
217
SetInheritedEffectiveTouchAction(TouchAction touch_action)218 void RemoteFrame::SetInheritedEffectiveTouchAction(TouchAction touch_action) {
219 if (inherited_effective_touch_action_ != touch_action)
220 GetRemoteFrameHostRemote().SetInheritedEffectiveTouchAction(touch_action);
221 inherited_effective_touch_action_ = touch_action;
222 }
223
BubbleLogicalScrollFromChildFrame(mojom::blink::ScrollDirection direction,ScrollGranularity granularity,Frame * child)224 bool RemoteFrame::BubbleLogicalScrollFromChildFrame(
225 mojom::blink::ScrollDirection direction,
226 ScrollGranularity granularity,
227 Frame* child) {
228 DCHECK(child->Client());
229 To<LocalFrame>(child)
230 ->GetLocalFrameHostRemote()
231 .BubbleLogicalScrollInParentFrame(direction, granularity);
232 return false;
233 }
234
RenderFallbackContent()235 void RemoteFrame::RenderFallbackContent() {
236 // TODO(ekaramad): If the owner renders its own content, then the current
237 // ContentFrame() should detach and free-up the OOPIF process (see
238 // https://crbug.com/850223).
239 auto* owner = DeprecatedLocalOwner();
240 DCHECK(IsA<HTMLObjectElement>(owner));
241 owner->RenderFallbackContent(this);
242 }
243
AddResourceTimingFromChild(mojom::blink::ResourceTimingInfoPtr timing)244 void RemoteFrame::AddResourceTimingFromChild(
245 mojom::blink::ResourceTimingInfoPtr timing) {
246 HTMLFrameOwnerElement* owner_element = To<HTMLFrameOwnerElement>(Owner());
247 DCHECK(owner_element);
248
249 // TODO(https://crbug.com/900700): Take a Mojo pending receiver for
250 // WorkerTimingContainer for navigation from the calling function.
251 DOMWindowPerformance::performance(*owner_element->GetDocument().domWindow())
252 ->AddResourceTiming(std::move(timing), owner_element->localName(),
253 /*worker_timing_receiver=*/mojo::NullReceiver());
254 }
255
DidStartLoading()256 void RemoteFrame::DidStartLoading() {
257 SetIsLoading(true);
258 }
259
DidStopLoading()260 void RemoteFrame::DidStopLoading() {
261 SetIsLoading(false);
262
263 // When a subframe finishes loading, the parent should check if *all*
264 // subframes have finished loading (which may mean that the parent can declare
265 // that the parent itself has finished loading). This remote-subframe-focused
266 // code has a local-subframe equivalent in FrameLoader::DidFinishNavigation.
267 Frame* parent = Tree().Parent();
268 if (parent)
269 parent->CheckCompleted();
270 }
271
DidFocus()272 void RemoteFrame::DidFocus() {
273 GetRemoteFrameHostRemote().DidFocusFrame();
274 }
275
SetView(RemoteFrameView * view)276 void RemoteFrame::SetView(RemoteFrameView* view) {
277 // Oilpan: as RemoteFrameView performs no finalization actions,
278 // no explicit Dispose() of it needed here. (cf. LocalFrameView::Dispose().)
279 view_ = view;
280 }
281
CreateView()282 void RemoteFrame::CreateView() {
283 // If the RemoteFrame does not have a LocalFrame parent, there's no need to
284 // create a EmbeddedContentView for it.
285 if (!DeprecatedLocalOwner())
286 return;
287
288 DCHECK(!DeprecatedLocalOwner()->OwnedEmbeddedContentView());
289
290 SetView(MakeGarbageCollected<RemoteFrameView>(this));
291
292 if (OwnerLayoutObject())
293 DeprecatedLocalOwner()->SetEmbeddedContentView(view_);
294 }
295
GetRemoteFrameHostRemote()296 mojom::blink::RemoteFrameHost& RemoteFrame::GetRemoteFrameHostRemote() {
297 return *remote_frame_host_remote_.get();
298 }
299
Client() const300 RemoteFrameClient* RemoteFrame::Client() const {
301 return static_cast<RemoteFrameClient*>(Frame::Client());
302 }
303
DidChangeVisibleToHitTesting()304 void RemoteFrame::DidChangeVisibleToHitTesting() {
305 if (!cc_layer_ || !is_surface_layer_)
306 return;
307
308 static_cast<cc::SurfaceLayer*>(cc_layer_)->SetHasPointerEventsNone(
309 IsIgnoredForHitTest());
310 }
311
SetReplicatedFeaturePolicyHeaderAndOpenerPolicies(const ParsedFeaturePolicy & parsed_header,const FeaturePolicy::FeatureState & opener_feature_state)312 void RemoteFrame::SetReplicatedFeaturePolicyHeaderAndOpenerPolicies(
313 const ParsedFeaturePolicy& parsed_header,
314 const FeaturePolicy::FeatureState& opener_feature_state) {
315 feature_policy_header_ = parsed_header;
316 if (RuntimeEnabledFeatures::FeaturePolicyForSandboxEnabled()) {
317 DCHECK(opener_feature_state.empty() || IsMainFrame());
318 if (OpenerFeatureState().empty()) {
319 SetOpenerFeatureState(opener_feature_state);
320 }
321 }
322 ApplyReplicatedFeaturePolicyHeader();
323 }
324
SetReplicatedSandboxFlags(mojom::blink::WebSandboxFlags flags)325 void RemoteFrame::SetReplicatedSandboxFlags(
326 mojom::blink::WebSandboxFlags flags) {
327 security_context_.ResetAndEnforceSandboxFlags(flags);
328 }
329
SetInsecureRequestPolicy(mojom::blink::InsecureRequestPolicy policy)330 void RemoteFrame::SetInsecureRequestPolicy(
331 mojom::blink::InsecureRequestPolicy policy) {
332 security_context_.SetInsecureRequestPolicy(policy);
333 }
334
SetInsecureNavigationsSet(const WebVector<unsigned> & set)335 void RemoteFrame::SetInsecureNavigationsSet(const WebVector<unsigned>& set) {
336 security_context_.SetInsecureNavigationsSet(set);
337 }
338
WillEnterFullscreen()339 void RemoteFrame::WillEnterFullscreen() {
340 // This should only ever be called when the FrameOwner is local.
341 HTMLFrameOwnerElement* owner_element = To<HTMLFrameOwnerElement>(Owner());
342
343 // Call |requestFullscreen()| on |ownerElement| to make it the pending
344 // fullscreen element in anticipation of the coming |didEnterFullscreen()|
345 // call.
346 //
347 // PrefixedForCrossProcessDescendant is necessary because:
348 // - The fullscreen element ready check and other checks should be bypassed.
349 // - |ownerElement| will need :-webkit-full-screen-ancestor style in addition
350 // to :fullscreen.
351 //
352 // TODO(alexmos): currently, this assumes prefixed requests, but in the
353 // future, this should plumb in information about which request type
354 // (prefixed or unprefixed) to use for firing fullscreen events.
355 Fullscreen::RequestFullscreen(
356 *owner_element, FullscreenOptions::Create(),
357 Fullscreen::RequestType::kPrefixedForCrossProcessDescendant);
358 }
359
AddReplicatedContentSecurityPolicies(WTF::Vector<network::mojom::blink::ContentSecurityPolicyHeaderPtr> headers)360 void RemoteFrame::AddReplicatedContentSecurityPolicies(
361 WTF::Vector<network::mojom::blink::ContentSecurityPolicyHeaderPtr>
362 headers) {
363 for (auto& header : headers) {
364 GetSecurityContext()->GetContentSecurityPolicy()->AddPolicyFromHeaderValue(
365 header->header_value, header->type, header->source);
366 }
367 }
368
ResetReplicatedContentSecurityPolicy()369 void RemoteFrame::ResetReplicatedContentSecurityPolicy() {
370 security_context_.ResetReplicatedContentSecurityPolicy();
371 }
372
EnforceInsecureNavigationsSet(const WTF::Vector<uint32_t> & set)373 void RemoteFrame::EnforceInsecureNavigationsSet(
374 const WTF::Vector<uint32_t>& set) {
375 security_context_.SetInsecureNavigationsSet(set);
376 }
377
SetFrameOwnerProperties(mojom::blink::FrameOwnerPropertiesPtr properties)378 void RemoteFrame::SetFrameOwnerProperties(
379 mojom::blink::FrameOwnerPropertiesPtr properties) {
380 Frame::ApplyFrameOwnerProperties(std::move(properties));
381 }
382
EnforceInsecureRequestPolicy(mojom::blink::InsecureRequestPolicy policy)383 void RemoteFrame::EnforceInsecureRequestPolicy(
384 mojom::blink::InsecureRequestPolicy policy) {
385 SetInsecureRequestPolicy(policy);
386 }
387
SetReplicatedOrigin(const scoped_refptr<const SecurityOrigin> & origin,bool is_potentially_trustworthy_unique_origin)388 void RemoteFrame::SetReplicatedOrigin(
389 const scoped_refptr<const SecurityOrigin>& origin,
390 bool is_potentially_trustworthy_unique_origin) {
391 scoped_refptr<SecurityOrigin> security_origin = origin->IsolatedCopy();
392 security_origin->SetOpaqueOriginIsPotentiallyTrustworthy(
393 is_potentially_trustworthy_unique_origin);
394 security_context_.SetReplicatedOrigin(security_origin);
395 ApplyReplicatedFeaturePolicyHeader();
396
397 // If the origin of a remote frame changed, the accessibility object for the
398 // owner element now points to a different child.
399 //
400 // TODO(dmazzoni, dcheng): there's probably a better way to solve this.
401 // Run SitePerProcessAccessibilityBrowserTest.TwoCrossSiteNavigations to
402 // ensure an alternate fix works. http://crbug.com/566222
403 FrameOwner* owner = Owner();
404 HTMLElement* owner_element = DynamicTo<HTMLFrameOwnerElement>(owner);
405 if (owner_element) {
406 AXObjectCache* cache = owner_element->GetDocument().ExistingAXObjectCache();
407 if (cache)
408 cache->ChildrenChanged(owner_element);
409 }
410 }
411
SetReplicatedAdFrameType(mojom::blink::AdFrameType ad_frame_type)412 void RemoteFrame::SetReplicatedAdFrameType(
413 mojom::blink::AdFrameType ad_frame_type) {
414 if (ad_frame_type_ == mojom::blink::AdFrameType::kNonAd) {
415 ad_frame_type_ = ad_frame_type;
416 } else {
417 DCHECK_EQ(ad_frame_type_, ad_frame_type);
418 }
419 }
420
DispatchLoadEventForFrameOwner()421 void RemoteFrame::DispatchLoadEventForFrameOwner() {
422 DCHECK(Owner()->IsLocal());
423 Owner()->DispatchLoad();
424 }
425
Collapse(bool collapsed)426 void RemoteFrame::Collapse(bool collapsed) {
427 FrameOwner* owner = Owner();
428 To<HTMLFrameOwnerElement>(owner)->SetCollapsed(collapsed);
429 }
430
Focus()431 void RemoteFrame::Focus() {
432 FocusImpl();
433 }
434
SetHadStickyUserActivationBeforeNavigation(bool value)435 void RemoteFrame::SetHadStickyUserActivationBeforeNavigation(bool value) {
436 Frame::SetHadStickyUserActivationBeforeNavigation(value);
437 }
438
SetNeedsOcclusionTracking(bool needs_tracking)439 void RemoteFrame::SetNeedsOcclusionTracking(bool needs_tracking) {
440 View()->SetNeedsOcclusionTracking(needs_tracking);
441 }
442
BubbleLogicalScroll(mojom::blink::ScrollDirection direction,ui::ScrollGranularity granularity)443 void RemoteFrame::BubbleLogicalScroll(mojom::blink::ScrollDirection direction,
444 ui::ScrollGranularity granularity) {
445 Frame* parent_frame = Client()->Parent();
446 DCHECK(parent_frame);
447 DCHECK(parent_frame->IsLocalFrame());
448
449 parent_frame->BubbleLogicalScrollFromChildFrame(direction, granularity, this);
450 }
451
UpdateUserActivationState(mojom::blink::UserActivationUpdateType update_type)452 void RemoteFrame::UpdateUserActivationState(
453 mojom::blink::UserActivationUpdateType update_type) {
454 switch (update_type) {
455 case mojom::blink::UserActivationUpdateType::kNotifyActivation:
456 NotifyUserActivationInLocalTree();
457 break;
458 case mojom::blink::UserActivationUpdateType::kConsumeTransientActivation:
459 ConsumeTransientUserActivationInLocalTree();
460 break;
461 case mojom::blink::UserActivationUpdateType::kClearActivation:
462 ClearUserActivationInLocalTree();
463 break;
464 case mojom::blink::UserActivationUpdateType::
465 kNotifyActivationPendingBrowserVerification:
466 NOTREACHED() << "Unexpected UserActivationUpdateType from browser";
467 break;
468 }
469 }
470
SetEmbeddingToken(const base::UnguessableToken & embedding_token)471 void RemoteFrame::SetEmbeddingToken(
472 const base::UnguessableToken& embedding_token) {
473 FrameOwner* owner = Owner();
474 To<HTMLFrameOwnerElement>(owner)->SetEmbeddingToken(embedding_token);
475 }
476
SetPageFocus(bool is_focused)477 void RemoteFrame::SetPageFocus(bool is_focused) {
478 WebFrame::FromFrame(this)->View()->SetFocus(is_focused);
479 }
480
ScrollRectToVisible(const gfx::Rect & rect_to_scroll,mojom::blink::ScrollIntoViewParamsPtr params)481 void RemoteFrame::ScrollRectToVisible(
482 const gfx::Rect& rect_to_scroll,
483 mojom::blink::ScrollIntoViewParamsPtr params) {
484 Element* owner_element = DeprecatedLocalOwner();
485 LayoutObject* owner_object = owner_element->GetLayoutObject();
486 if (!owner_object) {
487 // The LayoutObject could be nullptr by the time we get here. For instance
488 // <iframe>'s style might have been set to 'display: none' right after
489 // scrolling starts in the OOPIF's process (see https://crbug.com/777811).
490 return;
491 }
492
493 // Schedule the scroll.
494 PhysicalRect absolute_rect = owner_object->LocalToAncestorRect(
495 PhysicalRect(LayoutUnit(rect_to_scroll.x()),
496 LayoutUnit(rect_to_scroll.y()),
497 LayoutUnit(rect_to_scroll.width()),
498 LayoutUnit(rect_to_scroll.height())),
499 owner_object->View());
500
501 if (!params->zoom_into_rect ||
502 !owner_object->GetDocument().GetFrame()->LocalFrameRoot().IsMainFrame()) {
503 owner_object->ScrollRectToVisible(absolute_rect, std::move(params));
504 return;
505 }
506
507 // ZoomAndScrollToFocusedEditableElementRect will scroll only the layout and
508 // visual viewports. Ensure the element is actually visible in the viewport
509 // scrolling layer. (i.e. isn't clipped by some other content).
510 auto relative_element_bounds = params->relative_element_bounds;
511 auto relative_caret_bounds = params->relative_caret_bounds;
512
513 params->stop_at_main_frame_layout_viewport = true;
514 absolute_rect =
515 owner_object->ScrollRectToVisible(absolute_rect, std::move(params));
516
517 IntRect rect_in_document =
518 owner_object->GetDocument()
519 .GetFrame()
520 ->LocalFrameRoot()
521 .View()
522 ->RootFrameToDocument(EnclosingIntRect(
523 owner_element->GetDocument().View()->ConvertToRootFrame(
524 absolute_rect)));
525 IntRect element_bounds_in_document = EnclosingIntRect(
526 DeNormalizeRect(relative_element_bounds, rect_in_document));
527 IntRect caret_bounds_in_document = EnclosingIntRect(
528 DeNormalizeRect(relative_caret_bounds, rect_in_document));
529
530 // This is due to something such as scroll focused editable element into
531 // view on Android which also requires an automatic zoom into legible scale.
532 // This is handled by main frame's WebView.
533 WebFrame::FromFrame(this)->View()->ZoomAndScrollToFocusedEditableElementRect(
534 element_bounds_in_document, caret_bounds_in_document, true);
535 }
536
IntrinsicSizingInfoOfChildChanged(mojom::blink::IntrinsicSizingInfoPtr info)537 void RemoteFrame::IntrinsicSizingInfoOfChildChanged(
538 mojom::blink::IntrinsicSizingInfoPtr info) {
539 FrameOwner* owner = Owner();
540 // Only communication from HTMLPluginElement-owned subframes is allowed
541 // at present. This includes <embed> and <object> tags.
542 if (!owner || !owner->IsPlugin())
543 return;
544
545 // TODO(https://crbug.com/1044304): Should either remove the native
546 // C++ Blink type and use the Mojo type everywhere or typemap the
547 // Mojo type to the pre-existing native C++ Blink type.
548 IntrinsicSizingInfo sizing_info;
549 sizing_info.size = FloatSize(info->size);
550 sizing_info.aspect_ratio = FloatSize(info->aspect_ratio);
551 sizing_info.has_width = info->has_width;
552 sizing_info.has_height = info->has_height;
553 View()->SetIntrinsicSizeInfo(sizing_info);
554
555 owner->IntrinsicSizingInfoChanged();
556 }
557
558 // Update the proxy's SecurityContext with new sandbox flags or feature policy
559 // that were set during navigation. Unlike changes to the FrameOwner, which are
560 // handled by RenderFrameProxy::OnDidUpdateFramePolicy, these changes should be
561 // considered effective immediately.
562 //
563 // These flags / policy are needed on the remote frame's SecurityContext to
564 // ensure that sandbox flags and feature policy are inherited properly if this
565 // proxy ever parents a local frame.
DidSetFramePolicyHeaders(mojom::blink::WebSandboxFlags sandbox_flags,const Vector<ParsedFeaturePolicyDeclaration> & parsed_feature_policy)566 void RemoteFrame::DidSetFramePolicyHeaders(
567 mojom::blink::WebSandboxFlags sandbox_flags,
568 const Vector<ParsedFeaturePolicyDeclaration>& parsed_feature_policy) {
569 SetReplicatedSandboxFlags(sandbox_flags);
570 // Convert from WTF::Vector<ParsedFeaturePolicyDeclaration>
571 // to std::vector<ParsedFeaturePolicyDeclaration>, since ParsedFeaturePolicy
572 // is an alias for the later.
573 //
574 // TODO(crbug.com/1047273): Remove this conversion by switching
575 // ParsedFeaturePolicy to operate over Vector
576 ParsedFeaturePolicy parsed_feature_policy_copy(parsed_feature_policy.size());
577 for (size_t i = 0; i < parsed_feature_policy.size(); ++i)
578 parsed_feature_policy_copy[i] = parsed_feature_policy[i];
579 SetReplicatedFeaturePolicyHeaderAndOpenerPolicies(
580 parsed_feature_policy_copy, FeaturePolicy::FeatureState());
581 }
582
583 // Update the proxy's FrameOwner with new sandbox flags and container policy
584 // that were set by its parent in another process.
585 //
586 // Normally, when a frame's sandbox attribute is changed dynamically, the
587 // frame's FrameOwner is updated with the new sandbox flags right away, while
588 // the frame's SecurityContext is updated when the frame is navigated and the
589 // new sandbox flags take effect.
590 //
591 // Currently, there is no use case for a proxy's pending FrameOwner sandbox
592 // flags, so there's no message sent to proxies when the sandbox attribute is
593 // first updated. Instead, the active flags are updated when they take effect,
594 // by OnDidSetActiveSandboxFlags. The proxy's FrameOwner flags are updated here
595 // with the caveat that the FrameOwner won't learn about updates to its flags
596 // until they take effect.
DidUpdateFramePolicy(const FramePolicy & frame_policy)597 void RemoteFrame::DidUpdateFramePolicy(const FramePolicy& frame_policy) {
598 // At the moment, this is only used to replicate sandbox flags and container
599 // policy for frames with a remote owner.
600 SECURITY_CHECK(IsA<RemoteFrameOwner>(Owner()));
601 To<RemoteFrameOwner>(Owner())->SetFramePolicy(frame_policy);
602 }
603
GetMainFrameViewportSize() const604 IntSize RemoteFrame::GetMainFrameViewportSize() const {
605 HTMLFrameOwnerElement* owner = DeprecatedLocalOwner();
606 DCHECK(owner);
607 DCHECK(owner->GetDocument().GetFrame());
608 return owner->GetDocument().GetFrame()->GetMainFrameViewportSize();
609 }
610
GetMainFrameScrollOffset() const611 IntPoint RemoteFrame::GetMainFrameScrollOffset() const {
612 HTMLFrameOwnerElement* owner = DeprecatedLocalOwner();
613 DCHECK(owner);
614 DCHECK(owner->GetDocument().GetFrame());
615 return owner->GetDocument().GetFrame()->GetMainFrameScrollOffset();
616 }
617
IsIgnoredForHitTest() const618 bool RemoteFrame::IsIgnoredForHitTest() const {
619 HTMLFrameOwnerElement* owner = DeprecatedLocalOwner();
620 if (!owner || !owner->GetLayoutObject())
621 return false;
622
623 return owner->OwnerType() == FrameOwnerElementType::kPortal ||
624 !visible_to_hit_testing_;
625 }
626
SetCcLayer(cc::Layer * cc_layer,bool prevent_contents_opaque_changes,bool is_surface_layer)627 void RemoteFrame::SetCcLayer(cc::Layer* cc_layer,
628 bool prevent_contents_opaque_changes,
629 bool is_surface_layer) {
630 DCHECK(Owner());
631
632 cc_layer_ = cc_layer;
633 prevent_contents_opaque_changes_ = prevent_contents_opaque_changes;
634 is_surface_layer_ = is_surface_layer;
635 if (cc_layer_) {
636 if (is_surface_layer) {
637 static_cast<cc::SurfaceLayer*>(cc_layer_)->SetHasPointerEventsNone(
638 IsIgnoredForHitTest());
639 }
640 }
641
642 To<HTMLFrameOwnerElement>(Owner())->SetNeedsCompositingUpdate();
643 }
644
AdvanceFocus(mojom::blink::FocusType type,LocalFrame * source)645 void RemoteFrame::AdvanceFocus(mojom::blink::FocusType type,
646 LocalFrame* source) {
647 Client()->AdvanceFocus(type, source);
648 }
649
DetachChildren()650 void RemoteFrame::DetachChildren() {
651 using FrameVector = HeapVector<Member<Frame>>;
652 FrameVector children_to_detach;
653 children_to_detach.ReserveCapacity(Tree().ChildCount());
654 for (Frame* child = Tree().FirstChild(); child;
655 child = child->Tree().NextSibling())
656 children_to_detach.push_back(child);
657 for (const auto& child : children_to_detach)
658 child->Detach(FrameDetachType::kRemove);
659 }
660
ApplyReplicatedFeaturePolicyHeader()661 void RemoteFrame::ApplyReplicatedFeaturePolicyHeader() {
662 const FeaturePolicy* parent_feature_policy = nullptr;
663 if (Frame* parent_frame = Client()->Parent()) {
664 parent_feature_policy =
665 parent_frame->GetSecurityContext()->GetFeaturePolicy();
666 }
667 ParsedFeaturePolicy container_policy;
668 if (Owner())
669 container_policy = Owner()->GetFramePolicy().container_policy;
670 const FeaturePolicy::FeatureState& opener_feature_state =
671 OpenerFeatureState();
672 security_context_.InitializeFeaturePolicy(
673 feature_policy_header_, container_policy, parent_feature_policy,
674 opener_feature_state.empty() ? nullptr : &opener_feature_state);
675 }
676
BindToReceiver(blink::RemoteFrame * frame,mojo::PendingAssociatedReceiver<mojom::blink::RemoteFrame> receiver)677 void RemoteFrame::BindToReceiver(
678 blink::RemoteFrame* frame,
679 mojo::PendingAssociatedReceiver<mojom::blink::RemoteFrame> receiver) {
680 DCHECK(frame);
681 frame->receiver_.Bind(std::move(receiver));
682 }
683
684 } // namespace blink
685