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 "services/network/public/mojom/web_sandbox_flags.mojom-blink.h"
9 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
10 #include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-blink.h"
11 #include "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom-blink.h"
12 #include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h"
13 #include "third_party/blink/public/platform/interface_registry.h"
14 #include "third_party/blink/public/web/web_frame.h"
15 #include "third_party/blink/public/web/web_view.h"
16 #include "third_party/blink/renderer/bindings/core/v8/v8_fullscreen_options.h"
17 #include "third_party/blink/renderer/bindings/core/v8/window_proxy.h"
18 #include "third_party/blink/renderer/bindings/core/v8/window_proxy_manager.h"
19 #include "third_party/blink/renderer/core/events/message_event.h"
20 #include "third_party/blink/renderer/core/exported/web_view_impl.h"
21 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
22 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
23 #include "third_party/blink/renderer/core/frame/local_frame.h"
24 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
25 #include "third_party/blink/renderer/core/frame/remote_dom_window.h"
26 #include "third_party/blink/renderer/core/frame/remote_frame_client.h"
27 #include "third_party/blink/renderer/core/frame/remote_frame_owner.h"
28 #include "third_party/blink/renderer/core/frame/remote_frame_view.h"
29 #include "third_party/blink/renderer/core/frame/user_activation.h"
30 #include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
31 #include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
32 #include "third_party/blink/renderer/core/inspector/console_message.h"
33 #include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
34 #include "third_party/blink/renderer/core/layout/intrinsic_sizing_info.h"
35 #include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
36 #include "third_party/blink/renderer/core/layout/layout_view.h"
37 #include "third_party/blink/renderer/core/layout/text_autosizer.h"
38 #include "third_party/blink/renderer/core/loader/frame_load_request.h"
39 #include "third_party/blink/renderer/core/loader/frame_loader.h"
40 #include "third_party/blink/renderer/core/loader/mixed_content_checker.h"
41 #include "third_party/blink/renderer/core/messaging/blink_transferable_message.h"
42 #include "third_party/blink/renderer/core/page/page.h"
43 #include "third_party/blink/renderer/core/page/plugin_script_forbidden_scope.h"
44 #include "third_party/blink/renderer/core/paint/paint_layer.h"
45 #include "third_party/blink/renderer/core/probe/core_probes.h"
46 #include "third_party/blink/renderer/core/timing/dom_window_performance.h"
47 #include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
48 #include "third_party/blink/renderer/platform/heap/heap.h"
49 #include "third_party/blink/renderer/platform/heap/heap_allocator.h"
50 #include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h"
51 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
52 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h"
53 #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
54 #include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
55 #include "third_party/blink/renderer/platform/weborigin/security_policy.h"
56 
57 namespace blink {
58 
59 namespace {
60 
61 // Maintain a global (statically-allocated) hash map indexed by the the result
62 // of hashing the |frame_token| passed on creation of a RemoteFrame object.
63 typedef HeapHashMap<uint64_t, WeakMember<RemoteFrame>> RemoteFramesByTokenMap;
GetRemoteFramesMap()64 static RemoteFramesByTokenMap& GetRemoteFramesMap() {
65   DEFINE_STATIC_LOCAL(Persistent<RemoteFramesByTokenMap>, map,
66                       (MakeGarbageCollected<RemoteFramesByTokenMap>()));
67   return *map;
68 }
69 
DeNormalizeRect(const gfx::RectF & normalized,const IntRect & base)70 FloatRect DeNormalizeRect(const gfx::RectF& normalized, const IntRect& base) {
71   FloatRect result(normalized);
72   result.Scale(base.Width(), base.Height());
73   result.MoveBy(FloatPoint(base.Location()));
74   return result;
75 }
76 
77 }  // namespace
78 
79 // static
FromFrameToken(const base::UnguessableToken & frame_token)80 RemoteFrame* RemoteFrame::FromFrameToken(
81     const base::UnguessableToken& frame_token) {
82   RemoteFramesByTokenMap& remote_frames_map = GetRemoteFramesMap();
83   auto it = remote_frames_map.find(base::UnguessableTokenHash()(frame_token));
84   return it == remote_frames_map.end() ? nullptr : it->value.Get();
85 }
86 
87 // static
FromFrameToken(const RemoteFrameToken & frame_token)88 RemoteFrame* RemoteFrame::FromFrameToken(const RemoteFrameToken& frame_token) {
89   return FromFrameToken(frame_token.value());
90 }
91 
RemoteFrame(RemoteFrameClient * client,Page & page,FrameOwner * owner,Frame * parent,Frame * previous_sibling,FrameInsertType insert_type,const base::UnguessableToken & frame_token,WindowAgentFactory * inheriting_agent_factory,InterfaceRegistry * interface_registry,AssociatedInterfaceProvider * associated_interface_provider)92 RemoteFrame::RemoteFrame(
93     RemoteFrameClient* client,
94     Page& page,
95     FrameOwner* owner,
96     Frame* parent,
97     Frame* previous_sibling,
98     FrameInsertType insert_type,
99     const base::UnguessableToken& frame_token,
100     WindowAgentFactory* inheriting_agent_factory,
101     InterfaceRegistry* interface_registry,
102     AssociatedInterfaceProvider* associated_interface_provider)
103     : Frame(client,
104             page,
105             owner,
106             parent,
107             previous_sibling,
108             insert_type,
109             frame_token,
110             MakeGarbageCollected<RemoteWindowProxyManager>(*this),
111             inheriting_agent_factory),
112       interface_registry_(interface_registry
113                               ? interface_registry
114                               : InterfaceRegistry::GetEmptyInterfaceRegistry()),
115       task_runner_(page.GetPageScheduler()
116                        ->GetAgentGroupScheduler()
117                        .DefaultTaskRunner()) {
118   // TODO(crbug.com/1094850): Remove this check once the renderer is correctly
119   // handling errors during the creation of HTML portal elements, which would
120   // otherwise cause RemoteFrame() being created with empty frame tokens.
121   if (!frame_token.is_empty()) {
122     auto frame_tracking_result = GetRemoteFramesMap().insert(
123         base::UnguessableTokenHash()(frame_token), this);
124     CHECK(frame_tracking_result.stored_value) << "Inserting a duplicate item.";
125   }
126 
127   dom_window_ = MakeGarbageCollected<RemoteDOMWindow>(*this);
128 
129   interface_registry->AddAssociatedInterface(WTF::BindRepeating(
130       &RemoteFrame::BindToReceiver, WrapWeakPersistent(this)));
131 
132   DCHECK(task_runner_);
133   associated_interface_provider->GetInterface(
134       remote_frame_host_remote_.BindNewEndpointAndPassReceiver(task_runner_));
135 
136   UpdateInertIfPossible();
137   UpdateInheritedEffectiveTouchActionIfPossible();
138   UpdateVisibleToHitTesting();
139   Initialize();
140 }
141 
~RemoteFrame()142 RemoteFrame::~RemoteFrame() {
143   DCHECK(!view_);
144 }
145 
Trace(Visitor * visitor) const146 void RemoteFrame::Trace(Visitor* visitor) const {
147   visitor->Trace(view_);
148   visitor->Trace(security_context_);
149   Frame::Trace(visitor);
150 }
151 
Navigate(FrameLoadRequest & frame_request,WebFrameLoadType frame_load_type)152 void RemoteFrame::Navigate(FrameLoadRequest& frame_request,
153                            WebFrameLoadType frame_load_type) {
154   // RemoteFrame::Navigate doesn't support policies like
155   // kNavigationPolicyNewForegroundTab - such policies need to be handled via
156   // local frames.
157   DCHECK_EQ(kNavigationPolicyCurrentTab, frame_request.GetNavigationPolicy());
158 
159   if (HTMLFrameOwnerElement* element = DeprecatedLocalOwner())
160     element->CancelPendingLazyLoad();
161 
162   if (!navigation_rate_limiter().CanProceed())
163     return;
164 
165   frame_request.SetFrameType(IsMainFrame()
166                                  ? mojom::RequestContextFrameType::kTopLevel
167                                  : mojom::RequestContextFrameType::kNested);
168 
169   const KURL& url = frame_request.GetResourceRequest().Url();
170   auto* window = frame_request.GetOriginWindow();
171   if (!frame_request.CanDisplay(url)) {
172     if (window) {
173       window->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
174           mojom::blink::ConsoleMessageSource::kSecurity,
175           mojom::blink::ConsoleMessageLevel::kError,
176           "Not allowed to load local resource: " + url.ElidedString()));
177     }
178     return;
179   }
180 
181   // The process where this frame actually lives won't have sufficient
182   // information to upgrade the url, since it won't have access to the
183   // origin context. Do it now.
184   const FetchClientSettingsObject* fetch_client_settings_object = nullptr;
185   if (window) {
186     fetch_client_settings_object =
187         &window->Fetcher()->GetProperties().GetFetchClientSettingsObject();
188   }
189   MixedContentChecker::UpgradeInsecureRequest(
190       frame_request.GetResourceRequest(), fetch_client_settings_object, window,
191       frame_request.GetFrameType(),
192       window ? window->GetFrame()->GetContentSettingsClient() : nullptr);
193 
194   // Navigations in portal contexts do not create back/forward entries.
195   if (GetPage()->InsidePortal() &&
196       frame_load_type == WebFrameLoadType::kStandard) {
197     frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
198   }
199 
200   WebLocalFrame* initiator_frame =
201       window ? window->GetFrame()->Client()->GetWebFrame() : nullptr;
202 
203   bool is_opener_navigation = false;
204   bool initiator_frame_has_download_sandbox_flag = false;
205   bool initiator_frame_is_ad = false;
206 
207   if (window) {
208     is_opener_navigation = window->GetFrame()->Opener() == this;
209     initiator_frame_has_download_sandbox_flag =
210         window->IsSandboxed(network::mojom::blink::WebSandboxFlags::kDownloads);
211     initiator_frame_is_ad = window->GetFrame()->IsAdSubframe();
212     if (frame_request.ClientRedirectReason() != ClientNavigationReason::kNone) {
213       probe::FrameRequestedNavigation(window->GetFrame(), this, url,
214                                       frame_request.ClientRedirectReason(),
215                                       kNavigationPolicyCurrentTab);
216     }
217   }
218 
219   Client()->Navigate(frame_request.GetResourceRequest(), initiator_frame,
220                      frame_load_type == WebFrameLoadType::kReplaceCurrentItem,
221                      is_opener_navigation,
222                      initiator_frame_has_download_sandbox_flag,
223                      initiator_frame_is_ad, frame_request.GetBlobURLToken(),
224                      frame_request.Impression());
225 }
226 
DetachImpl(FrameDetachType type)227 void RemoteFrame::DetachImpl(FrameDetachType type) {
228   PluginScriptForbiddenScope forbid_plugin_destructor_scripting;
229   DetachChildren();
230   if (!Client())
231     return;
232 
233   // Clean up the frame's view if needed. A remote frame only has a view if
234   // the parent is a local frame.
235   if (view_)
236     view_->Dispose();
237   GetWindowProxyManager()->ClearForClose();
238   SetView(nullptr);
239   // ... the RemoteDOMWindow will need to be informed of detachment,
240   // as otherwise it will keep a strong reference back to this RemoteFrame.
241   // That combined with wrappers (owned and kept alive by RemoteFrame) keeping
242   // persistent strong references to RemoteDOMWindow will prevent the GCing
243   // of all these objects. Break the cycle by notifying of detachment.
244   To<RemoteDOMWindow>(dom_window_.Get())->FrameDetached();
245   if (cc_layer_)
246     SetCcLayer(nullptr, false, false);
247   receiver_.reset();
248   main_frame_receiver_.reset();
249 }
250 
DetachDocument()251 bool RemoteFrame::DetachDocument() {
252   DetachChildren();
253   return !!GetPage();
254 }
255 
CheckCompleted()256 void RemoteFrame::CheckCompleted() {
257   // Notify the client so that the corresponding LocalFrame can do the check.
258   GetRemoteFrameHostRemote().CheckCompleted();
259 }
260 
GetSecurityContext() const261 const RemoteSecurityContext* RemoteFrame::GetSecurityContext() const {
262   return &security_context_;
263 }
264 
ShouldClose()265 bool RemoteFrame::ShouldClose() {
266   // TODO(nasko): Implement running the beforeunload handler in the actual
267   // LocalFrame running in a different process and getting back a real result.
268   return true;
269 }
270 
SetIsInert(bool inert)271 void RemoteFrame::SetIsInert(bool inert) {
272   if (inert != is_inert_)
273     GetRemoteFrameHostRemote().SetIsInert(inert);
274   is_inert_ = inert;
275 }
276 
SetInheritedEffectiveTouchAction(TouchAction touch_action)277 void RemoteFrame::SetInheritedEffectiveTouchAction(TouchAction touch_action) {
278   if (inherited_effective_touch_action_ != touch_action)
279     GetRemoteFrameHostRemote().SetInheritedEffectiveTouchAction(touch_action);
280   inherited_effective_touch_action_ = touch_action;
281 }
282 
BubbleLogicalScrollFromChildFrame(mojom::blink::ScrollDirection direction,ScrollGranularity granularity,Frame * child)283 bool RemoteFrame::BubbleLogicalScrollFromChildFrame(
284     mojom::blink::ScrollDirection direction,
285     ScrollGranularity granularity,
286     Frame* child) {
287   DCHECK(child->Client());
288   To<LocalFrame>(child)
289       ->GetLocalFrameHostRemote()
290       .BubbleLogicalScrollInParentFrame(direction, granularity);
291   return false;
292 }
293 
RenderFallbackContent()294 void RemoteFrame::RenderFallbackContent() {
295   // TODO(ekaramad): If the owner renders its own content, then the current
296   // ContentFrame() should detach and free-up the OOPIF process (see
297   // https://crbug.com/850223).
298   auto* owner = DeprecatedLocalOwner();
299   DCHECK(IsA<HTMLObjectElement>(owner));
300   owner->RenderFallbackContent(this);
301 }
302 
AddResourceTimingFromChild(mojom::blink::ResourceTimingInfoPtr timing)303 void RemoteFrame::AddResourceTimingFromChild(
304     mojom::blink::ResourceTimingInfoPtr timing) {
305   HTMLFrameOwnerElement* owner_element = To<HTMLFrameOwnerElement>(Owner());
306   DCHECK(owner_element);
307 
308   // TODO(https://crbug.com/900700): Take a Mojo pending receiver for
309   // WorkerTimingContainer for navigation from the calling function.
310   DOMWindowPerformance::performance(*owner_element->GetDocument().domWindow())
311       ->AddResourceTiming(std::move(timing), owner_element->localName(),
312                           /*worker_timing_receiver=*/mojo::NullReceiver(),
313                           owner_element->GetDocument().GetExecutionContext());
314 }
315 
DidStartLoading()316 void RemoteFrame::DidStartLoading() {
317   SetIsLoading(true);
318 }
319 
DidStopLoading()320 void RemoteFrame::DidStopLoading() {
321   SetIsLoading(false);
322 
323   // When a subframe finishes loading, the parent should check if *all*
324   // subframes have finished loading (which may mean that the parent can declare
325   // that the parent itself has finished loading). This remote-subframe-focused
326   // code has a local-subframe equivalent in FrameLoader::DidFinishNavigation.
327   Frame* parent = Tree().Parent();
328   if (parent)
329     parent->CheckCompleted();
330 }
331 
DidFocus()332 void RemoteFrame::DidFocus() {
333   GetRemoteFrameHostRemote().DidFocusFrame();
334 }
335 
SetView(RemoteFrameView * view)336 void RemoteFrame::SetView(RemoteFrameView* view) {
337   // Oilpan: as RemoteFrameView performs no finalization actions,
338   // no explicit Dispose() of it needed here. (cf. LocalFrameView::Dispose().)
339   view_ = view;
340 }
341 
CreateView()342 void RemoteFrame::CreateView() {
343   // If the RemoteFrame does not have a LocalFrame parent, there's no need to
344   // create a EmbeddedContentView for it.
345   if (!DeprecatedLocalOwner())
346     return;
347 
348   DCHECK(!DeprecatedLocalOwner()->OwnedEmbeddedContentView());
349 
350   SetView(MakeGarbageCollected<RemoteFrameView>(this));
351 
352   if (OwnerLayoutObject())
353     DeprecatedLocalOwner()->SetEmbeddedContentView(view_);
354 }
355 
ForwardPostMessage(MessageEvent * message_event,base::Optional<base::UnguessableToken> cluster_id,scoped_refptr<const SecurityOrigin> target_security_origin,LocalFrame * source_frame)356 void RemoteFrame::ForwardPostMessage(
357     MessageEvent* message_event,
358     base::Optional<base::UnguessableToken> cluster_id,
359     scoped_refptr<const SecurityOrigin> target_security_origin,
360     LocalFrame* source_frame) {
361   base::Optional<base::UnguessableToken> source_token;
362   if (source_frame)
363     source_token = source_frame->GetFrameToken();
364 
365   String source_origin = message_event->origin();
366   String target_origin = g_empty_string;
367   if (target_security_origin)
368     target_origin = target_security_origin->ToString();
369 
370   GetRemoteFrameHostRemote().RouteMessageEvent(
371       source_token, source_origin, target_origin,
372       BlinkTransferableMessage::FromMessageEvent(message_event, cluster_id));
373 }
374 
GetRemoteFrameHostRemote()375 mojom::blink::RemoteFrameHost& RemoteFrame::GetRemoteFrameHostRemote() {
376   return *remote_frame_host_remote_.get();
377 }
378 
GetRemoteAssociatedInterfaces()379 AssociatedInterfaceProvider* RemoteFrame::GetRemoteAssociatedInterfaces() {
380   DCHECK(Client());
381   return Client()->GetRemoteAssociatedInterfaces();
382 }
383 
Client() const384 RemoteFrameClient* RemoteFrame::Client() const {
385   return static_cast<RemoteFrameClient*>(Frame::Client());
386 }
387 
DidChangeVisibleToHitTesting()388 void RemoteFrame::DidChangeVisibleToHitTesting() {
389   if (!cc_layer_ || !is_surface_layer_)
390     return;
391 
392   static_cast<cc::SurfaceLayer*>(cc_layer_)->SetHasPointerEventsNone(
393       IsIgnoredForHitTest());
394 }
395 
SetReplicatedFeaturePolicyHeaderAndOpenerPolicies(const ParsedFeaturePolicy & parsed_header,const FeaturePolicyFeatureState & opener_feature_state)396 void RemoteFrame::SetReplicatedFeaturePolicyHeaderAndOpenerPolicies(
397     const ParsedFeaturePolicy& parsed_header,
398     const FeaturePolicyFeatureState& opener_feature_state) {
399   feature_policy_header_ = parsed_header;
400   if (RuntimeEnabledFeatures::FeaturePolicyForSandboxEnabled()) {
401     DCHECK(opener_feature_state.empty() || IsMainFrame());
402     if (OpenerFeatureState().empty()) {
403       SetOpenerFeatureState(opener_feature_state);
404     }
405   }
406   ApplyReplicatedFeaturePolicyHeader();
407 }
408 
SetReplicatedSandboxFlags(network::mojom::blink::WebSandboxFlags flags)409 void RemoteFrame::SetReplicatedSandboxFlags(
410     network::mojom::blink::WebSandboxFlags flags) {
411   security_context_.ResetAndEnforceSandboxFlags(flags);
412 }
413 
SetInsecureRequestPolicy(mojom::blink::InsecureRequestPolicy policy)414 void RemoteFrame::SetInsecureRequestPolicy(
415     mojom::blink::InsecureRequestPolicy policy) {
416   security_context_.SetInsecureRequestPolicy(policy);
417 }
418 
SetInsecureNavigationsSet(const WebVector<unsigned> & set)419 void RemoteFrame::SetInsecureNavigationsSet(const WebVector<unsigned>& set) {
420   security_context_.SetInsecureNavigationsSet(set);
421 }
422 
WillEnterFullscreen(mojom::blink::FullscreenOptionsPtr request_options)423 void RemoteFrame::WillEnterFullscreen(
424     mojom::blink::FullscreenOptionsPtr request_options) {
425   // This should only ever be called when the FrameOwner is local.
426   HTMLFrameOwnerElement* owner_element = To<HTMLFrameOwnerElement>(Owner());
427 
428   // Call |requestFullscreen()| on |ownerElement| to make it the pending
429   // fullscreen element in anticipation of the coming |didEnterFullscreen()|
430   // call.
431   //
432   // ForCrossProcessDescendant is necessary because:
433   //  - The fullscreen element ready check and other checks should be bypassed.
434   //  - |ownerElement| will need :-webkit-full-screen-ancestor style in addition
435   //    to :fullscreen.
436   FullscreenRequestType request_type =
437       (request_options->is_prefixed ? FullscreenRequestType::kPrefixed
438                                     : FullscreenRequestType::kUnprefixed) |
439       (request_options->is_xr_overlay ? FullscreenRequestType::kForXrOverlay
440                                       : FullscreenRequestType::kNull) |
441       FullscreenRequestType::kForCrossProcessDescendant;
442 
443   Fullscreen::RequestFullscreen(*owner_element, FullscreenOptions::Create(),
444                                 request_type);
445 }
446 
AddReplicatedContentSecurityPolicies(WTF::Vector<network::mojom::blink::ContentSecurityPolicyHeaderPtr> headers)447 void RemoteFrame::AddReplicatedContentSecurityPolicies(
448     WTF::Vector<network::mojom::blink::ContentSecurityPolicyHeaderPtr>
449         headers) {
450   for (auto& header : headers) {
451     GetSecurityContext()->GetContentSecurityPolicy()->AddPolicyFromHeaderValue(
452         header->header_value, header->type, header->source);
453   }
454 }
455 
ResetReplicatedContentSecurityPolicy()456 void RemoteFrame::ResetReplicatedContentSecurityPolicy() {
457   security_context_.ResetReplicatedContentSecurityPolicy();
458 }
459 
EnforceInsecureNavigationsSet(const WTF::Vector<uint32_t> & set)460 void RemoteFrame::EnforceInsecureNavigationsSet(
461     const WTF::Vector<uint32_t>& set) {
462   security_context_.SetInsecureNavigationsSet(set);
463 }
464 
SetFrameOwnerProperties(mojom::blink::FrameOwnerPropertiesPtr properties)465 void RemoteFrame::SetFrameOwnerProperties(
466     mojom::blink::FrameOwnerPropertiesPtr properties) {
467   Frame::ApplyFrameOwnerProperties(std::move(properties));
468 }
469 
EnforceInsecureRequestPolicy(mojom::blink::InsecureRequestPolicy policy)470 void RemoteFrame::EnforceInsecureRequestPolicy(
471     mojom::blink::InsecureRequestPolicy policy) {
472   SetInsecureRequestPolicy(policy);
473 }
474 
SetReplicatedOrigin(const scoped_refptr<const SecurityOrigin> & origin,bool is_potentially_trustworthy_unique_origin)475 void RemoteFrame::SetReplicatedOrigin(
476     const scoped_refptr<const SecurityOrigin>& origin,
477     bool is_potentially_trustworthy_unique_origin) {
478   scoped_refptr<SecurityOrigin> security_origin = origin->IsolatedCopy();
479   security_origin->SetOpaqueOriginIsPotentiallyTrustworthy(
480       is_potentially_trustworthy_unique_origin);
481   security_context_.SetReplicatedOrigin(security_origin);
482   ApplyReplicatedFeaturePolicyHeader();
483 
484   // If the origin of a remote frame changed, the accessibility object for the
485   // owner element now points to a different child.
486   //
487   // TODO(dmazzoni, dcheng): there's probably a better way to solve this.
488   // Run SitePerProcessAccessibilityBrowserTest.TwoCrossSiteNavigations to
489   // ensure an alternate fix works.  http://crbug.com/566222
490   FrameOwner* owner = Owner();
491   HTMLElement* owner_element = DynamicTo<HTMLFrameOwnerElement>(owner);
492   if (owner_element) {
493     AXObjectCache* cache = owner_element->GetDocument().ExistingAXObjectCache();
494     if (cache)
495       cache->ChildrenChanged(owner_element);
496   }
497 }
498 
SetReplicatedAdFrameType(mojom::blink::AdFrameType ad_frame_type)499 void RemoteFrame::SetReplicatedAdFrameType(
500     mojom::blink::AdFrameType ad_frame_type) {
501   if (ad_frame_type_ == mojom::blink::AdFrameType::kNonAd) {
502     ad_frame_type_ = ad_frame_type;
503   } else {
504     DCHECK_EQ(ad_frame_type_, ad_frame_type);
505   }
506 }
507 
SetReplicatedName(const String & name,const String & unique_name)508 void RemoteFrame::SetReplicatedName(const String& name,
509                                     const String& unique_name) {
510   Tree().SetName(AtomicString(name));
511   unique_name_ = unique_name;
512 }
513 
DispatchLoadEventForFrameOwner()514 void RemoteFrame::DispatchLoadEventForFrameOwner() {
515   DCHECK(Owner()->IsLocal());
516   Owner()->DispatchLoad();
517 }
518 
Collapse(bool collapsed)519 void RemoteFrame::Collapse(bool collapsed) {
520   FrameOwner* owner = Owner();
521   To<HTMLFrameOwnerElement>(owner)->SetCollapsed(collapsed);
522 }
523 
Focus()524 void RemoteFrame::Focus() {
525   FocusImpl();
526 }
527 
SetHadStickyUserActivationBeforeNavigation(bool value)528 void RemoteFrame::SetHadStickyUserActivationBeforeNavigation(bool value) {
529   Frame::SetHadStickyUserActivationBeforeNavigation(value);
530 }
531 
SetNeedsOcclusionTracking(bool needs_tracking)532 void RemoteFrame::SetNeedsOcclusionTracking(bool needs_tracking) {
533   View()->SetNeedsOcclusionTracking(needs_tracking);
534 }
535 
BubbleLogicalScroll(mojom::blink::ScrollDirection direction,ui::ScrollGranularity granularity)536 void RemoteFrame::BubbleLogicalScroll(mojom::blink::ScrollDirection direction,
537                                       ui::ScrollGranularity granularity) {
538   Frame* parent_frame = Parent();
539   DCHECK(parent_frame);
540   DCHECK(parent_frame->IsLocalFrame());
541 
542   parent_frame->BubbleLogicalScrollFromChildFrame(direction, granularity, this);
543 }
544 
UpdateUserActivationState(mojom::blink::UserActivationUpdateType update_type,mojom::blink::UserActivationNotificationType notification_type)545 void RemoteFrame::UpdateUserActivationState(
546     mojom::blink::UserActivationUpdateType update_type,
547     mojom::blink::UserActivationNotificationType notification_type) {
548   switch (update_type) {
549     case mojom::blink::UserActivationUpdateType::kNotifyActivation:
550       NotifyUserActivationInFrameTree(notification_type);
551       break;
552     case mojom::blink::UserActivationUpdateType::kConsumeTransientActivation:
553       ConsumeTransientUserActivationInFrameTree();
554       break;
555     case mojom::blink::UserActivationUpdateType::kClearActivation:
556       ClearUserActivationInFrameTree();
557       break;
558     case mojom::blink::UserActivationUpdateType::
559         kNotifyActivationPendingBrowserVerification:
560       NOTREACHED() << "Unexpected UserActivationUpdateType from browser";
561       break;
562   }
563 }
564 
SetEmbeddingToken(const base::UnguessableToken & embedding_token)565 void RemoteFrame::SetEmbeddingToken(
566     const base::UnguessableToken& embedding_token) {
567   DCHECK(IsA<HTMLFrameOwnerElement>(Owner()));
568   Frame::SetEmbeddingToken(embedding_token);
569 }
570 
SetPageFocus(bool is_focused)571 void RemoteFrame::SetPageFocus(bool is_focused) {
572   WebFrame::FromFrame(this)->View()->SetFocus(is_focused);
573 }
574 
ScrollRectToVisible(const gfx::Rect & rect_to_scroll,mojom::blink::ScrollIntoViewParamsPtr params)575 void RemoteFrame::ScrollRectToVisible(
576     const gfx::Rect& rect_to_scroll,
577     mojom::blink::ScrollIntoViewParamsPtr params) {
578   Element* owner_element = DeprecatedLocalOwner();
579   LayoutObject* owner_object = owner_element->GetLayoutObject();
580   if (!owner_object) {
581     // The LayoutObject could be nullptr by the time we get here. For instance
582     // <iframe>'s style might have been set to 'display: none' right after
583     // scrolling starts in the OOPIF's process (see https://crbug.com/777811).
584     return;
585   }
586 
587   // Schedule the scroll.
588   PhysicalRect absolute_rect = owner_object->LocalToAncestorRect(
589       PhysicalRect(LayoutUnit(rect_to_scroll.x()),
590                    LayoutUnit(rect_to_scroll.y()),
591                    LayoutUnit(rect_to_scroll.width()),
592                    LayoutUnit(rect_to_scroll.height())),
593       owner_object->View());
594 
595   if (!params->zoom_into_rect ||
596       !owner_object->GetDocument().GetFrame()->LocalFrameRoot().IsMainFrame()) {
597     owner_object->ScrollRectToVisible(absolute_rect, std::move(params));
598     return;
599   }
600 
601   // ZoomAndScrollToFocusedEditableElementRect will scroll only the layout and
602   // visual viewports. Ensure the element is actually visible in the viewport
603   // scrolling layer. (i.e. isn't clipped by some other content).
604   auto relative_element_bounds = params->relative_element_bounds;
605   auto relative_caret_bounds = params->relative_caret_bounds;
606 
607   params->stop_at_main_frame_layout_viewport = true;
608   absolute_rect =
609       owner_object->ScrollRectToVisible(absolute_rect, std::move(params));
610 
611   IntRect rect_in_document =
612       owner_object->GetDocument()
613           .GetFrame()
614           ->LocalFrameRoot()
615           .View()
616           ->RootFrameToDocument(EnclosingIntRect(
617               owner_element->GetDocument().View()->ConvertToRootFrame(
618                   absolute_rect)));
619   IntRect element_bounds_in_document = EnclosingIntRect(
620       DeNormalizeRect(relative_element_bounds, rect_in_document));
621   IntRect caret_bounds_in_document = EnclosingIntRect(
622       DeNormalizeRect(relative_caret_bounds, rect_in_document));
623 
624   // This is due to something such as scroll focused editable element into
625   // view on Android which also requires an automatic zoom into legible scale.
626   // This is handled by main frame's WebView.
627   WebViewImpl* web_view =
628       static_cast<WebViewImpl*>(WebFrame::FromFrame(this)->View());
629   web_view->ZoomAndScrollToFocusedEditableElementRect(
630       element_bounds_in_document, caret_bounds_in_document, true);
631 }
632 
IntrinsicSizingInfoOfChildChanged(mojom::blink::IntrinsicSizingInfoPtr info)633 void RemoteFrame::IntrinsicSizingInfoOfChildChanged(
634     mojom::blink::IntrinsicSizingInfoPtr info) {
635   FrameOwner* owner = Owner();
636   // Only communication from HTMLPluginElement-owned subframes is allowed
637   // at present. This includes <embed> and <object> tags.
638   if (!owner || !owner->IsPlugin())
639     return;
640 
641   // TODO(https://crbug.com/1044304): Should either remove the native
642   // C++ Blink type and use the Mojo type everywhere or typemap the
643   // Mojo type to the pre-existing native C++ Blink type.
644   IntrinsicSizingInfo sizing_info;
645   sizing_info.size = FloatSize(info->size);
646   sizing_info.aspect_ratio = FloatSize(info->aspect_ratio);
647   sizing_info.has_width = info->has_width;
648   sizing_info.has_height = info->has_height;
649   View()->SetIntrinsicSizeInfo(sizing_info);
650 
651   owner->IntrinsicSizingInfoChanged();
652 }
653 
654 // Update the proxy's SecurityContext with new sandbox flags or feature policy
655 // that were set during navigation. Unlike changes to the FrameOwner, which are
656 // handled by RemoteFrame::DidUpdateFramePolicy, these changes should be
657 // considered effective immediately.
658 //
659 // These flags / policy are needed on the remote frame's SecurityContext to
660 // ensure that sandbox flags and feature policy are inherited properly if this
661 // proxy ever parents a local frame.
DidSetFramePolicyHeaders(network::mojom::blink::WebSandboxFlags sandbox_flags,const WTF::Vector<ParsedFeaturePolicyDeclaration> & parsed_feature_policy)662 void RemoteFrame::DidSetFramePolicyHeaders(
663     network::mojom::blink::WebSandboxFlags sandbox_flags,
664     const WTF::Vector<ParsedFeaturePolicyDeclaration>& parsed_feature_policy) {
665   SetReplicatedSandboxFlags(sandbox_flags);
666   // Convert from WTF::Vector<ParsedFeaturePolicyDeclaration>
667   // to std::vector<ParsedFeaturePolicyDeclaration>, since ParsedFeaturePolicy
668   // is an alias for the later.
669   //
670   // TODO(crbug.com/1047273): Remove this conversion by switching
671   // ParsedFeaturePolicy to operate over Vector
672   ParsedFeaturePolicy parsed_feature_policy_copy(parsed_feature_policy.size());
673   for (size_t i = 0; i < parsed_feature_policy.size(); ++i)
674     parsed_feature_policy_copy[i] = parsed_feature_policy[i];
675   SetReplicatedFeaturePolicyHeaderAndOpenerPolicies(
676       parsed_feature_policy_copy, FeaturePolicyFeatureState());
677 }
678 
679 // Update the proxy's FrameOwner with new sandbox flags and container policy
680 // that were set by its parent in another process.
681 //
682 // Normally, when a frame's sandbox attribute is changed dynamically, the
683 // frame's FrameOwner is updated with the new sandbox flags right away, while
684 // the frame's SecurityContext is updated when the frame is navigated and the
685 // new sandbox flags take effect.
686 //
687 // Currently, there is no use case for a proxy's pending FrameOwner sandbox
688 // flags, so there's no message sent to proxies when the sandbox attribute is
689 // first updated.  Instead, the active flags are updated when they take effect,
690 // by OnDidSetActiveSandboxFlags. The proxy's FrameOwner flags are updated here
691 // with the caveat that the FrameOwner won't learn about updates to its flags
692 // until they take effect.
DidUpdateFramePolicy(const FramePolicy & frame_policy)693 void RemoteFrame::DidUpdateFramePolicy(const FramePolicy& frame_policy) {
694   // At the moment, this is only used to replicate sandbox flags and container
695   // policy for frames with a remote owner.
696   SECURITY_CHECK(IsA<RemoteFrameOwner>(Owner()));
697   To<RemoteFrameOwner>(Owner())->SetFramePolicy(frame_policy);
698 }
699 
UpdateOpener(const base::Optional<base::UnguessableToken> & opener_frame_token)700 void RemoteFrame::UpdateOpener(
701     const base::Optional<base::UnguessableToken>& opener_frame_token) {
702   if (auto* web_frame = WebFrame::FromFrame(this)) {
703     Frame* opener_frame = nullptr;
704     if (opener_frame_token)
705       opener_frame = Frame::ResolveFrame(opener_frame_token.value());
706     SetOpenerDoNotNotify(opener_frame);
707   }
708 }
709 
GetMainFrameViewportSize() const710 IntSize RemoteFrame::GetMainFrameViewportSize() const {
711   HTMLFrameOwnerElement* owner = DeprecatedLocalOwner();
712   DCHECK(owner);
713   DCHECK(owner->GetDocument().GetFrame());
714   return owner->GetDocument().GetFrame()->GetMainFrameViewportSize();
715 }
716 
GetMainFrameScrollOffset() const717 IntPoint RemoteFrame::GetMainFrameScrollOffset() const {
718   HTMLFrameOwnerElement* owner = DeprecatedLocalOwner();
719   DCHECK(owner);
720   DCHECK(owner->GetDocument().GetFrame());
721   return owner->GetDocument().GetFrame()->GetMainFrameScrollOffset();
722 }
723 
SetOpener(Frame * opener_frame)724 void RemoteFrame::SetOpener(Frame* opener_frame) {
725   if (Opener() == opener_frame)
726     return;
727 
728   auto* web_frame = WebFrame::FromFrame(this);
729   if (web_frame) {
730     // A proxy shouldn't normally be disowning its opener.  It is possible to
731     // get here when a proxy that is being detached clears its opener, in
732     // which case there is no need to notify the browser process.
733     if (opener_frame) {
734       // Only a LocalFrame (i.e., the caller of window.open) should be able to
735       // update another frame's opener.
736       DCHECK(opener_frame->IsLocalFrame());
737       GetRemoteFrameHostRemote().DidChangeOpener(
738           opener_frame ? base::Optional<base::UnguessableToken>(
739                              opener_frame->GetFrameToken())
740                        : base::nullopt);
741     }
742   }
743   SetOpenerDoNotNotify(opener_frame);
744 }
745 
UpdateTextAutosizerPageInfo(mojom::blink::TextAutosizerPageInfoPtr mojo_remote_page_info)746 void RemoteFrame::UpdateTextAutosizerPageInfo(
747     mojom::blink::TextAutosizerPageInfoPtr mojo_remote_page_info) {
748   // Only propagate the remote page info if our main frame is remote.
749   DCHECK(IsMainFrame());
750   Frame* root_frame = GetPage()->MainFrame();
751   DCHECK(root_frame->IsRemoteFrame());
752   if (*mojo_remote_page_info == GetPage()->TextAutosizerPageInfo())
753     return;
754 
755   GetPage()->SetTextAutosizerPageInfo(*mojo_remote_page_info);
756   TextAutosizer::UpdatePageInfoInAllFrames(root_frame);
757 }
758 
WasAttachedAsRemoteMainFrame()759 void RemoteFrame::WasAttachedAsRemoteMainFrame() {
760   interface_registry_->AddAssociatedInterface(WTF::BindRepeating(
761       &RemoteFrame::BindToMainFrameReceiver, WrapWeakPersistent(this)));
762 }
763 
GetFrameSinkId()764 viz::FrameSinkId RemoteFrame::GetFrameSinkId() {
765   return Client()->GetFrameSinkId();
766 }
767 
IsIgnoredForHitTest() const768 bool RemoteFrame::IsIgnoredForHitTest() const {
769   HTMLFrameOwnerElement* owner = DeprecatedLocalOwner();
770   if (!owner || !owner->GetLayoutObject())
771     return false;
772 
773   return owner->OwnerType() == mojom::blink::FrameOwnerElementType::kPortal ||
774          !visible_to_hit_testing_;
775 }
776 
SetCcLayer(cc::Layer * cc_layer,bool prevent_contents_opaque_changes,bool is_surface_layer)777 void RemoteFrame::SetCcLayer(cc::Layer* cc_layer,
778                              bool prevent_contents_opaque_changes,
779                              bool is_surface_layer) {
780   DCHECK(Owner());
781 
782   cc_layer_ = cc_layer;
783   prevent_contents_opaque_changes_ = prevent_contents_opaque_changes;
784   is_surface_layer_ = is_surface_layer;
785   if (cc_layer_) {
786     if (is_surface_layer) {
787       static_cast<cc::SurfaceLayer*>(cc_layer_)->SetHasPointerEventsNone(
788           IsIgnoredForHitTest());
789     }
790   }
791   HTMLFrameOwnerElement* owner = To<HTMLFrameOwnerElement>(Owner());
792   owner->SetNeedsCompositingUpdate();
793 
794   if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
795     // New layers for remote frames are controlled by Blink's embedder.
796     // To ensure the new surface is painted, we need to repaint the frame
797     // owner's PaintLayer.
798     LayoutBoxModelObject* layout_object = owner->GetLayoutBoxModelObject();
799     if (layout_object && layout_object->Layer())
800       layout_object->Layer()->SetNeedsRepaint();
801   }
802 }
803 
AdvanceFocus(mojom::blink::FocusType type,LocalFrame * source)804 void RemoteFrame::AdvanceFocus(mojom::blink::FocusType type,
805                                LocalFrame* source) {
806   GetRemoteFrameHostRemote().AdvanceFocus(type, source->GetFrameToken());
807 }
808 
DetachChildren()809 void RemoteFrame::DetachChildren() {
810   using FrameVector = HeapVector<Member<Frame>>;
811   FrameVector children_to_detach;
812   children_to_detach.ReserveCapacity(Tree().ChildCount());
813   for (Frame* child = Tree().FirstChild(); child;
814        child = child->Tree().NextSibling())
815     children_to_detach.push_back(child);
816   for (const auto& child : children_to_detach)
817     child->Detach(FrameDetachType::kRemove);
818 }
819 
ApplyReplicatedFeaturePolicyHeader()820 void RemoteFrame::ApplyReplicatedFeaturePolicyHeader() {
821   const FeaturePolicy* parent_feature_policy = nullptr;
822   if (Frame* parent_frame = Parent()) {
823     parent_feature_policy =
824         parent_frame->GetSecurityContext()->GetFeaturePolicy();
825   }
826   ParsedFeaturePolicy container_policy;
827   if (Owner())
828     container_policy = Owner()->GetFramePolicy().container_policy;
829   const FeaturePolicyFeatureState& opener_feature_state = OpenerFeatureState();
830   security_context_.InitializeFeaturePolicy(
831       feature_policy_header_, container_policy, parent_feature_policy,
832       opener_feature_state.empty() ? nullptr : &opener_feature_state);
833 }
834 
BindToReceiver(RemoteFrame * frame,mojo::PendingAssociatedReceiver<mojom::blink::RemoteFrame> receiver)835 void RemoteFrame::BindToReceiver(
836     RemoteFrame* frame,
837     mojo::PendingAssociatedReceiver<mojom::blink::RemoteFrame> receiver) {
838   DCHECK(frame);
839   frame->receiver_.Bind(std::move(receiver), frame->task_runner_);
840 }
841 
BindToMainFrameReceiver(RemoteFrame * frame,mojo::PendingAssociatedReceiver<mojom::blink::RemoteMainFrame> receiver)842 void RemoteFrame::BindToMainFrameReceiver(
843     RemoteFrame* frame,
844     mojo::PendingAssociatedReceiver<mojom::blink::RemoteMainFrame> receiver) {
845   DCHECK(frame);
846   frame->main_frame_receiver_.Bind(std::move(receiver), frame->task_runner_);
847 }
848 
849 }  // namespace blink
850