| // Copyright 2014 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "content/renderer/render_frame_proxy.h" | 
 |  | 
 | #include <stdint.h> | 
 | #include <map> | 
 | #include <utility> | 
 |  | 
 | #include "base/command_line.h" | 
 | #include "base/lazy_instance.h" | 
 | #include "components/viz/common/features.h" | 
 | #include "content/common/content_switches_internal.h" | 
 | #include "content/common/frame_message_structs.h" | 
 | #include "content/common/frame_owner_properties.h" | 
 | #include "content/common/frame_replication_state.h" | 
 | #include "content/common/input_messages.h" | 
 | #include "content/common/page_messages.h" | 
 | #include "content/common/swapped_out_messages.h" | 
 | #include "content/common/view_messages.h" | 
 | #include "content/public/common/content_client.h" | 
 | #include "content/public/common/content_switches.h" | 
 | #include "content/public/common/screen_info.h" | 
 | #include "content/public/common/use_zoom_for_dsf_policy.h" | 
 | #include "content/public/renderer/content_renderer_client.h" | 
 | #include "content/renderer/child_frame_compositing_helper.h" | 
 | #include "content/renderer/frame_owner_properties.h" | 
 | #include "content/renderer/loader/web_url_request_util.h" | 
 | #include "content/renderer/render_frame_impl.h" | 
 | #include "content/renderer/render_thread_impl.h" | 
 | #include "content/renderer/render_view_impl.h" | 
 | #include "content/renderer/render_widget.h" | 
 | #include "content/renderer/resource_timing_info_conversions.h" | 
 | #include "ipc/ipc_message_macros.h" | 
 | #include "printing/buildflags/buildflags.h" | 
 | #include "third_party/blink/public/common/feature_policy/feature_policy.h" | 
 | #include "third_party/blink/public/common/frame/frame_policy.h" | 
 | #include "third_party/blink/public/platform/url_conversion.h" | 
 | #include "third_party/blink/public/platform/web_rect.h" | 
 | #include "third_party/blink/public/platform/web_resource_timing_info.h" | 
 | #include "third_party/blink/public/platform/web_string.h" | 
 | #include "third_party/blink/public/web/web_local_frame.h" | 
 | #include "third_party/blink/public/web/web_triggering_event_info.h" | 
 | #include "third_party/blink/public/web/web_user_gesture_indicator.h" | 
 | #include "third_party/blink/public/web/web_view.h" | 
 | #include "ui/base/ui_base_features.h" | 
 | #include "ui/gfx/geometry/size_conversions.h" | 
 |  | 
 | #if defined(USE_AURA) | 
 | #include "content/renderer/mus/mus_embedded_frame.h" | 
 | #include "content/renderer/mus/renderer_window_tree_client.h" | 
 | #endif | 
 |  | 
 | #if BUILDFLAG(ENABLE_PRINTING) | 
 | // nogncheck because dependency on //printing is conditional upon | 
 | // enable_basic_printing flags. | 
 | #include "printing/metafile_skia_wrapper.h"  // nogncheck | 
 | #include "printing/pdf_metafile_skia.h"      // nogncheck | 
 | #endif | 
 |  | 
 | namespace content { | 
 |  | 
 | namespace { | 
 |  | 
 | // Facilitates lookup of RenderFrameProxy by routing_id. | 
 | typedef std::map<int, RenderFrameProxy*> RoutingIDProxyMap; | 
 | static base::LazyInstance<RoutingIDProxyMap>::DestructorAtExit | 
 |     g_routing_id_proxy_map = LAZY_INSTANCE_INITIALIZER; | 
 |  | 
 | // Facilitates lookup of RenderFrameProxy by WebRemoteFrame. | 
 | typedef std::map<blink::WebRemoteFrame*, RenderFrameProxy*> FrameProxyMap; | 
 | base::LazyInstance<FrameProxyMap>::DestructorAtExit g_frame_proxy_map = | 
 |     LAZY_INSTANCE_INITIALIZER; | 
 |  | 
 | }  // namespace | 
 |  | 
 | // static | 
 | RenderFrameProxy* RenderFrameProxy::CreateProxyToReplaceFrame( | 
 |     RenderFrameImpl* frame_to_replace, | 
 |     int routing_id, | 
 |     blink::WebTreeScopeType scope) { | 
 |   CHECK_NE(routing_id, MSG_ROUTING_NONE); | 
 |  | 
 |   std::unique_ptr<RenderFrameProxy> proxy(new RenderFrameProxy(routing_id)); | 
 |   proxy->unique_name_ = frame_to_replace->unique_name(); | 
 |   proxy->devtools_frame_token_ = frame_to_replace->GetDevToolsFrameToken(); | 
 |  | 
 |   // When a RenderFrame is replaced by a RenderProxy, the WebRemoteFrame should | 
 |   // always come from WebRemoteFrame::create and a call to WebFrame::swap must | 
 |   // follow later. | 
 |   blink::WebRemoteFrame* web_frame = | 
 |       blink::WebRemoteFrame::Create(scope, proxy.get()); | 
 |  | 
 |   // If frame_to_replace has a RenderFrameProxy parent, then its | 
 |   // RenderWidget will be destroyed along with it, so the new | 
 |   // RenderFrameProxy uses its parent's RenderWidget. | 
 |   RenderWidget* widget = | 
 |       (!frame_to_replace->GetWebFrame()->Parent() || | 
 |        frame_to_replace->GetWebFrame()->Parent()->IsWebLocalFrame()) | 
 |           ? frame_to_replace->GetRenderWidget() | 
 |           : RenderFrameProxy::FromWebFrame( | 
 |                 frame_to_replace->GetWebFrame()->Parent()->ToWebRemoteFrame()) | 
 |                 ->render_widget(); | 
 |   proxy->Init(web_frame, frame_to_replace->render_view(), widget); | 
 |   return proxy.release(); | 
 | } | 
 |  | 
 | RenderFrameProxy* RenderFrameProxy::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) { | 
 |   RenderFrameProxy* parent = nullptr; | 
 |   if (parent_routing_id != MSG_ROUTING_NONE) { | 
 |     parent = RenderFrameProxy::FromRoutingID(parent_routing_id); | 
 |     // It is possible that the parent proxy has been detached in this renderer | 
 |     // process, just as the parent's real frame was creating this child frame. | 
 |     // In this case, do not create the proxy. See https://crbug.com/568670. | 
 |     if (!parent) | 
 |       return nullptr; | 
 |   } | 
 |  | 
 |   std::unique_ptr<RenderFrameProxy> proxy(new RenderFrameProxy(routing_id)); | 
 |   proxy->devtools_frame_token_ = devtools_frame_token; | 
 |   RenderViewImpl* render_view = nullptr; | 
 |   RenderWidget* render_widget = nullptr; | 
 |   blink::WebRemoteFrame* web_frame = nullptr; | 
 |  | 
 |   if (!parent) { | 
 |     // Create a top level WebRemoteFrame. | 
 |     render_view = RenderViewImpl::FromRoutingID(render_view_routing_id); | 
 |     web_frame = blink::WebRemoteFrame::CreateMainFrame( | 
 |         render_view->GetWebView(), proxy.get(), opener); | 
 |     render_widget = render_view->GetWidget(); | 
 |  | 
 |     // If the RenderView is reused by this proxy after having been used for a | 
 |     // pending RenderFrame that was discarded, its swapped out state needs to | 
 |     // be updated, as the OnSwapOut flow which normally does this won't happen | 
 |     // in that case.  See https://crbug.com/653746 and | 
 |     // https://crbug.com/651980. | 
 |     if (!render_widget->is_swapped_out()) | 
 |       render_widget->SetSwappedOut(true); | 
 |   } else { | 
 |     // Create a frame under an existing parent. The parent is always expected | 
 |     // to be a RenderFrameProxy, because navigations initiated by local frames | 
 |     // should not wind up here. | 
 |  | 
 |     web_frame = parent->web_frame()->CreateRemoteChild( | 
 |         replicated_state.scope, | 
 |         blink::WebString::FromUTF8(replicated_state.name), | 
 |         replicated_state.frame_policy.sandbox_flags, | 
 |         replicated_state.frame_policy.container_policy, proxy.get(), opener); | 
 |     proxy->unique_name_ = replicated_state.unique_name; | 
 |     render_view = parent->render_view(); | 
 |     render_widget = parent->render_widget(); | 
 |   } | 
 |  | 
 |   proxy->Init(web_frame, render_view, render_widget); | 
 |  | 
 |   // Initialize proxy's WebRemoteFrame with the security origin and other | 
 |   // replicated information. | 
 |   // TODO(dcheng): Calling this when parent_routing_id != MSG_ROUTING_NONE is | 
 |   // mostly redundant, since we already pass the name and sandbox flags in | 
 |   // createLocalChild(). We should update the Blink interface so it also takes | 
 |   // the origin. Then it will be clear that the replication call is only needed | 
 |   // for the case of setting up a main frame proxy. | 
 |   proxy->SetReplicatedState(replicated_state); | 
 |  | 
 |   return proxy.release(); | 
 | } | 
 |  | 
 | // static | 
 | RenderFrameProxy* RenderFrameProxy::FromRoutingID(int32_t routing_id) { | 
 |   RoutingIDProxyMap* proxies = g_routing_id_proxy_map.Pointer(); | 
 |   RoutingIDProxyMap::iterator it = proxies->find(routing_id); | 
 |   return it == proxies->end() ? NULL : it->second; | 
 | } | 
 |  | 
 | // static | 
 | RenderFrameProxy* RenderFrameProxy::FromWebFrame( | 
 |     blink::WebRemoteFrame* web_frame) { | 
 |   // TODO(dcheng): Turn this into a DCHECK() if it doesn't crash on canary. | 
 |   CHECK(web_frame); | 
 |   FrameProxyMap::iterator iter = g_frame_proxy_map.Get().find(web_frame); | 
 |   if (iter != g_frame_proxy_map.Get().end()) { | 
 |     RenderFrameProxy* proxy = iter->second; | 
 |     DCHECK_EQ(web_frame, proxy->web_frame()); | 
 |     return proxy; | 
 |   } | 
 |   // Reaching this is not expected: this implies that the |web_frame| in | 
 |   // question is not managed by the content API, or the associated | 
 |   // RenderFrameProxy is already deleted--in which case, it's not safe to touch | 
 |   // |web_frame|. | 
 |   NOTREACHED(); | 
 |   return nullptr; | 
 | } | 
 |  | 
 | RenderFrameProxy::RenderFrameProxy(int routing_id) | 
 |     : routing_id_(routing_id), | 
 |       provisional_frame_routing_id_(MSG_ROUTING_NONE), | 
 |       web_frame_(nullptr), | 
 |       render_view_(nullptr), | 
 |       render_widget_(nullptr) { | 
 |   std::pair<RoutingIDProxyMap::iterator, bool> result = | 
 |       g_routing_id_proxy_map.Get().insert(std::make_pair(routing_id_, this)); | 
 |   CHECK(result.second) << "Inserting a duplicate item."; | 
 |   RenderThread::Get()->AddRoute(routing_id_, this); | 
 | } | 
 |  | 
 | RenderFrameProxy::~RenderFrameProxy() { | 
 |   render_widget_->UnregisterRenderFrameProxy(this); | 
 |  | 
 |   CHECK(!web_frame_); | 
 |   RenderThread::Get()->RemoveRoute(routing_id_); | 
 |   g_routing_id_proxy_map.Get().erase(routing_id_); | 
 | } | 
 |  | 
 | void RenderFrameProxy::Init(blink::WebRemoteFrame* web_frame, | 
 |                             RenderViewImpl* render_view, | 
 |                             RenderWidget* render_widget) { | 
 |   CHECK(web_frame); | 
 |   CHECK(render_view); | 
 |   CHECK(render_widget); | 
 |  | 
 |   web_frame_ = web_frame; | 
 |   render_view_ = render_view; | 
 |   render_widget_ = render_widget; | 
 |  | 
 |   render_widget_->RegisterRenderFrameProxy(this); | 
 |  | 
 |   std::pair<FrameProxyMap::iterator, bool> result = | 
 |       g_frame_proxy_map.Get().insert(std::make_pair(web_frame_, this)); | 
 |   CHECK(result.second) << "Inserted a duplicate item."; | 
 |  | 
 |   enable_surface_synchronization_ = features::IsSurfaceSynchronizationEnabled(); | 
 |  | 
 |   compositing_helper_ = std::make_unique<ChildFrameCompositingHelper>(this); | 
 |  | 
 |   pending_visual_properties_.screen_info = | 
 |       render_widget_->GetOriginalScreenInfo(); | 
 |  | 
 | #if defined(USE_AURA) | 
 |   if (!features::IsAshInBrowserProcess()) { | 
 |     RendererWindowTreeClient* renderer_window_tree_client = | 
 |         RendererWindowTreeClient::Get(render_widget_->routing_id()); | 
 |     // It's possible a MusEmbeddedFrame has already been scheduled for creation | 
 |     // (that is, RendererWindowTreeClient::Embed() was called). Call to | 
 |     // OnRenderFrameProxyCreated() to potentially get the MusEmbeddedFrame. | 
 |     // OnRenderFrameProxyCreated() returns null if Embed() was not called. | 
 |     mus_embedded_frame_ = | 
 |         renderer_window_tree_client->OnRenderFrameProxyCreated(this); | 
 |   } | 
 | #endif | 
 | } | 
 |  | 
 | void RenderFrameProxy::ResendVisualProperties() { | 
 |   // Reset |sent_visual_properties_| in order to allocate a new | 
 |   // viz::LocalSurfaceId. | 
 |   sent_visual_properties_ = base::nullopt; | 
 |   SynchronizeVisualProperties(); | 
 | } | 
 |  | 
 | void RenderFrameProxy::WillBeginCompositorFrame() { | 
 |   if (compositing_helper_->primary_surface_id().is_valid()) { | 
 |     FrameHostMsg_HittestData_Params params; | 
 |     params.surface_id = compositing_helper_->primary_surface_id(); | 
 |     params.ignored_for_hittest = web_frame_->IsIgnoredForHitTest(); | 
 |     render_widget_->QueueMessage( | 
 |         new FrameHostMsg_HittestData(render_widget_->routing_id(), params), | 
 |         MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE); | 
 |   } | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnScreenInfoChanged(const ScreenInfo& screen_info) { | 
 |   pending_visual_properties_.screen_info = screen_info; | 
 |   if (crashed_) { | 
 |     // Update the sad page to match the current ScreenInfo. | 
 |     compositing_helper_->ChildFrameGone(local_frame_size(), | 
 |                                         screen_info.device_scale_factor); | 
 |     return; | 
 |   } | 
 |   SynchronizeVisualProperties(); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnZoomLevelChanged(double zoom_level) { | 
 |   pending_visual_properties_.zoom_level = zoom_level; | 
 |   SynchronizeVisualProperties(); | 
 | } | 
 |  | 
 | void RenderFrameProxy::UpdateCaptureSequenceNumber( | 
 |     uint32_t capture_sequence_number) { | 
 |   pending_visual_properties_.capture_sequence_number = capture_sequence_number; | 
 |   SynchronizeVisualProperties(); | 
 | } | 
 |  | 
 | void RenderFrameProxy::SetReplicatedState(const FrameReplicationState& state) { | 
 |   DCHECK(web_frame_); | 
 |  | 
 |   web_frame_->SetReplicatedOrigin( | 
 |       state.origin, state.has_potentially_trustworthy_unique_origin); | 
 |  | 
 | #if DCHECK_IS_ON() | 
 |   blink::WebSecurityOrigin security_origin_before_sandbox_flags = | 
 |       web_frame_->GetSecurityOrigin(); | 
 | #endif | 
 |  | 
 |   web_frame_->SetReplicatedSandboxFlags(state.active_sandbox_flags); | 
 |  | 
 | #if DCHECK_IS_ON() | 
 |   // If |state.has_potentially_trustworthy_unique_origin| is set, | 
 |   // - |state.origin| should be unique (this is checked in | 
 |   //   blink::SecurityOrigin::SetUniqueOriginIsPotentiallyTrustworthy() in | 
 |   //   SetReplicatedOrigin()), and thus | 
 |   // - The security origin is not updated by SetReplicatedSandboxFlags() and | 
 |   //   thus we don't have to apply |has_potentially_trustworthy_unique_origin| | 
 |   //   flag after SetReplicatedSandboxFlags(). | 
 |   if (state.has_potentially_trustworthy_unique_origin) | 
 |     DCHECK(security_origin_before_sandbox_flags == | 
 |            web_frame_->GetSecurityOrigin()); | 
 | #endif | 
 |  | 
 |   web_frame_->SetReplicatedName(blink::WebString::FromUTF8(state.name)); | 
 |   web_frame_->SetReplicatedInsecureRequestPolicy(state.insecure_request_policy); | 
 |   web_frame_->SetReplicatedInsecureNavigationsSet( | 
 |       state.insecure_navigations_set); | 
 |   web_frame_->SetReplicatedFeaturePolicyHeader(state.feature_policy_header); | 
 |   if (state.has_received_user_gesture) { | 
 |     web_frame_->UpdateUserActivationState( | 
 |         blink::UserActivationUpdateType::kNotifyActivation); | 
 |   } | 
 |   web_frame_->SetHasReceivedUserGestureBeforeNavigation( | 
 |       state.has_received_user_gesture_before_nav); | 
 |  | 
 |   web_frame_->ResetReplicatedContentSecurityPolicy(); | 
 |   OnAddContentSecurityPolicies(state.accumulated_csp_headers); | 
 | } | 
 |  | 
 | // Update the proxy's FrameOwner with new sandbox flags and container policy | 
 | // that were set by its parent in another process. | 
 | // | 
 | // Normally, when a frame's sandbox attribute is changed dynamically, the | 
 | // frame's FrameOwner is updated with the new sandbox flags right away, while | 
 | // the frame's SecurityContext is updated when the frame is navigated and the | 
 | // new sandbox flags take effect. | 
 | // | 
 | // Currently, there is no use case for a proxy's pending FrameOwner sandbox | 
 | // flags, so there's no message sent to proxies when the sandbox attribute is | 
 | // first updated.  Instead, the active flags are updated when they take effect, | 
 | // by OnDidSetActiveSandboxFlags. The proxy's FrameOwner flags are updated here | 
 | // with the caveat that the FrameOwner won't learn about updates to its flags | 
 | // until they take effect. | 
 | void RenderFrameProxy::OnDidUpdateFramePolicy( | 
 |     const blink::FramePolicy& frame_policy) { | 
 |   DCHECK(web_frame()->Parent()); | 
 |   web_frame_->SetFrameOwnerPolicy(frame_policy.sandbox_flags, | 
 |                                   frame_policy.container_policy); | 
 | } | 
 |  | 
 | // Update the proxy's SecurityContext with new sandbox flags or feature policy | 
 | // that were set during navigation. Unlike changes to the FrameOwner, which are | 
 | // handled by OnDidUpdateFramePolicy, these changes should be considered | 
 | // effective immediately. | 
 | // | 
 | // These flags / policy are needed on the remote frame's SecurityContext to | 
 | // ensure that sandbox flags and feature policy are inherited properly if this | 
 | // proxy ever parents a local frame. | 
 | void RenderFrameProxy::OnDidSetFramePolicyHeaders( | 
 |     blink::WebSandboxFlags active_sandbox_flags, | 
 |     blink::ParsedFeaturePolicy feature_policy_header) { | 
 |   web_frame_->SetReplicatedSandboxFlags(active_sandbox_flags); | 
 |   web_frame_->SetReplicatedFeaturePolicyHeader(feature_policy_header); | 
 | } | 
 |  | 
 | bool RenderFrameProxy::OnMessageReceived(const IPC::Message& msg) { | 
 |   // Forward Page IPCs to the RenderView. | 
 |   if ((IPC_MESSAGE_CLASS(msg) == PageMsgStart)) { | 
 |     if (render_view()) | 
 |       return render_view()->OnMessageReceived(msg); | 
 |  | 
 |     return false; | 
 |   } | 
 |  | 
 |   bool handled = true; | 
 |   IPC_BEGIN_MESSAGE_MAP(RenderFrameProxy, msg) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_DeleteProxy, OnDeleteProxy) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_ChildFrameProcessGone, OnChildFrameProcessGone) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_FirstSurfaceActivation, | 
 |                         OnFirstSurfaceActivation) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_IntrinsicSizingInfoOfChildChanged, | 
 |                         OnIntrinsicSizingInfoOfChildChanged) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_UpdateOpener, OnUpdateOpener) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_ViewChanged, OnViewChanged) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_DidStartLoading, OnDidStartLoading) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_DidStopLoading, OnDidStopLoading) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_DidUpdateFramePolicy, OnDidUpdateFramePolicy) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_DidSetFramePolicyHeaders, | 
 |                         OnDidSetFramePolicyHeaders) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_ForwardResourceTimingToParent, | 
 |                         OnForwardResourceTimingToParent) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_DispatchLoad, OnDispatchLoad) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_Collapse, OnCollapse) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_DidUpdateName, OnDidUpdateName) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_AddContentSecurityPolicies, | 
 |                         OnAddContentSecurityPolicies) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_ResetContentSecurityPolicy, | 
 |                         OnResetContentSecurityPolicy) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_EnforceInsecureRequestPolicy, | 
 |                         OnEnforceInsecureRequestPolicy) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_EnforceInsecureNavigationsSet, | 
 |                         OnEnforceInsecureNavigationsSet) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_SetFrameOwnerProperties, | 
 |                         OnSetFrameOwnerProperties) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_DidUpdateOrigin, OnDidUpdateOrigin) | 
 |     IPC_MESSAGE_HANDLER(InputMsg_SetFocus, OnSetPageFocus) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_DidUpdateVisualProperties, | 
 |                         OnDidUpdateVisualProperties) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_EnableAutoResize, OnEnableAutoResize) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_DisableAutoResize, OnDisableAutoResize) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_SetFocusedFrame, OnSetFocusedFrame) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_WillEnterFullscreen, OnWillEnterFullscreen) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_UpdateUserActivationState, | 
 |                         OnUpdateUserActivationState) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_ScrollRectToVisible, OnScrollRectToVisible) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_BubbleLogicalScroll, OnBubbleLogicalScroll) | 
 |     IPC_MESSAGE_HANDLER(FrameMsg_SetHasReceivedUserGestureBeforeNavigation, | 
 |                         OnSetHasReceivedUserGestureBeforeNavigation) | 
 |     IPC_MESSAGE_UNHANDLED(handled = false) | 
 |   IPC_END_MESSAGE_MAP() | 
 |  | 
 |   // Note: If |handled| is true, |this| may have been deleted. | 
 |   return handled; | 
 | } | 
 |  | 
 | bool RenderFrameProxy::Send(IPC::Message* message) { | 
 |   return RenderThread::Get()->Send(message); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnDeleteProxy() { | 
 |   DCHECK(web_frame_); | 
 |   web_frame_->Detach(); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnChildFrameProcessGone() { | 
 |   crashed_ = true; | 
 |   compositing_helper_->ChildFrameGone(local_frame_size(), | 
 |                                       screen_info().device_scale_factor); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnFirstSurfaceActivation( | 
 |     const viz::SurfaceInfo& surface_info) { | 
 |   // If this WebFrame has already been detached, its parent will be null. This | 
 |   // can happen when swapping a WebRemoteFrame with a WebLocalFrame, where this | 
 |   // message may arrive after the frame was removed from the frame tree, but | 
 |   // before the frame has been destroyed. http://crbug.com/446575. | 
 |   if (!web_frame()->Parent()) | 
 |     return; | 
 |  | 
 |   if (!enable_surface_synchronization_) { | 
 |     compositing_helper_->SetPrimarySurfaceId( | 
 |         surface_info.id(), local_frame_size(), | 
 |         cc::DeadlinePolicy::UseDefaultDeadline()); | 
 |   } | 
 |   compositing_helper_->SetFallbackSurfaceId(surface_info.id(), | 
 |                                             local_frame_size()); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnIntrinsicSizingInfoOfChildChanged( | 
 |     blink::WebIntrinsicSizingInfo sizing_info) { | 
 |   web_frame()->IntrinsicSizingInfoChanged(sizing_info); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnUpdateOpener(int opener_routing_id) { | 
 |   blink::WebFrame* opener = RenderFrameImpl::ResolveOpener(opener_routing_id); | 
 |   web_frame_->SetOpener(opener); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnDidStartLoading() { | 
 |   web_frame_->DidStartLoading(); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnViewChanged( | 
 |     const FrameMsg_ViewChanged_Params& params) { | 
 |   crashed_ = false; | 
 |   // In mash the FrameSinkId comes from RendererWindowTreeClient. | 
 |   if (features::IsAshInBrowserProcess()) | 
 |     frame_sink_id_ = *params.frame_sink_id; | 
 |  | 
 |   // Resend the FrameRects and allocate a new viz::LocalSurfaceId when the view | 
 |   // changes. | 
 |   ResendVisualProperties(); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnDidStopLoading() { | 
 |   web_frame_->DidStopLoading(); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnForwardResourceTimingToParent( | 
 |     const ResourceTimingInfo& info) { | 
 |   web_frame_->ForwardResourceTimingToParent( | 
 |       ResourceTimingInfoToWebResourceTimingInfo(info)); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnDispatchLoad() { | 
 |   web_frame_->DispatchLoadEventForFrameOwner(); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnCollapse(bool collapsed) { | 
 |   web_frame_->Collapse(collapsed); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnDidUpdateName(const std::string& name, | 
 |                                        const std::string& unique_name) { | 
 |   web_frame_->SetReplicatedName(blink::WebString::FromUTF8(name)); | 
 |   unique_name_ = unique_name; | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnAddContentSecurityPolicies( | 
 |     const std::vector<ContentSecurityPolicyHeader>& headers) { | 
 |   for (const auto& header : headers) { | 
 |     web_frame_->AddReplicatedContentSecurityPolicyHeader( | 
 |         blink::WebString::FromUTF8(header.header_value), header.type, | 
 |         header.source); | 
 |   } | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnResetContentSecurityPolicy() { | 
 |   web_frame_->ResetReplicatedContentSecurityPolicy(); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnEnforceInsecureRequestPolicy( | 
 |     blink::WebInsecureRequestPolicy policy) { | 
 |   web_frame_->SetReplicatedInsecureRequestPolicy(policy); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnEnforceInsecureNavigationsSet( | 
 |     const std::vector<uint32_t>& set) { | 
 |   web_frame_->SetReplicatedInsecureNavigationsSet(set); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnSetFrameOwnerProperties( | 
 |     const FrameOwnerProperties& properties) { | 
 |   web_frame_->SetFrameOwnerProperties( | 
 |       ConvertFrameOwnerPropertiesToWebFrameOwnerProperties(properties)); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnDidUpdateOrigin( | 
 |     const url::Origin& origin, | 
 |     bool is_potentially_trustworthy_unique_origin) { | 
 |   web_frame_->SetReplicatedOrigin(origin, | 
 |                                   is_potentially_trustworthy_unique_origin); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnSetPageFocus(bool is_focused) { | 
 |   render_view_->SetFocus(is_focused); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnSetFocusedFrame() { | 
 |   // This uses focusDocumentView rather than setFocusedFrame so that blur | 
 |   // events are properly dispatched on any currently focused elements. | 
 |   render_view_->webview()->FocusDocumentView(web_frame_); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnWillEnterFullscreen() { | 
 |   web_frame_->WillEnterFullscreen(); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnUpdateUserActivationState( | 
 |     blink::UserActivationUpdateType update_type) { | 
 |   web_frame_->UpdateUserActivationState(update_type); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnScrollRectToVisible( | 
 |     const gfx::Rect& rect_to_scroll, | 
 |     const blink::WebScrollIntoViewParams& params) { | 
 |   web_frame_->ScrollRectToVisible(rect_to_scroll, params); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnBubbleLogicalScroll( | 
 |     blink::WebScrollDirection direction, | 
 |     blink::WebScrollGranularity granularity) { | 
 |   web_frame_->BubbleLogicalScroll(direction, granularity); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnDidUpdateVisualProperties( | 
 |     const cc::RenderFrameMetadata& metadata) { | 
 |   if (!parent_local_surface_id_allocator_.UpdateFromChild( | 
 |           metadata.local_surface_id.value_or(viz::LocalSurfaceId()))) { | 
 |     return; | 
 |   } | 
 |  | 
 |   // The viz::LocalSurfaceId has changed so we call SynchronizeVisualProperties | 
 |   // here to embed it. | 
 |   SynchronizeVisualProperties(); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnEnableAutoResize(const gfx::Size& min_size, | 
 |                                           const gfx::Size& max_size) { | 
 |   pending_visual_properties_.auto_resize_enabled = true; | 
 |   pending_visual_properties_.min_size_for_auto_resize = min_size; | 
 |   pending_visual_properties_.max_size_for_auto_resize = max_size; | 
 |   SynchronizeVisualProperties(); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnDisableAutoResize() { | 
 |   pending_visual_properties_.auto_resize_enabled = false; | 
 |   SynchronizeVisualProperties(); | 
 | } | 
 |  | 
 | #if defined(USE_AURA) | 
 | void RenderFrameProxy::SetMusEmbeddedFrame( | 
 |     std::unique_ptr<MusEmbeddedFrame> mus_embedded_frame) { | 
 |   mus_embedded_frame_ = std::move(mus_embedded_frame); | 
 | } | 
 | #endif | 
 |  | 
 | void RenderFrameProxy::SynchronizeVisualProperties() { | 
 |   if (!frame_sink_id_.is_valid() || crashed_) | 
 |     return; | 
 |  | 
 |   // Note that the following flag is true if the capture sequence number | 
 |   // actually changed. That is, it is false if we did not have | 
 |   // |sent_visual_properties_|, which is different from | 
 |   // |synchronized_props_changed| below. | 
 |   bool capture_sequence_number_changed = | 
 |       sent_visual_properties_ && | 
 |       sent_visual_properties_->capture_sequence_number != | 
 |           pending_visual_properties_.capture_sequence_number; | 
 |  | 
 |   bool synchronized_props_changed = | 
 |       !sent_visual_properties_ || | 
 |       sent_visual_properties_->auto_resize_enabled != | 
 |           pending_visual_properties_.auto_resize_enabled || | 
 |       sent_visual_properties_->min_size_for_auto_resize != | 
 |           pending_visual_properties_.min_size_for_auto_resize || | 
 |       sent_visual_properties_->max_size_for_auto_resize != | 
 |           pending_visual_properties_.max_size_for_auto_resize || | 
 |       sent_visual_properties_->local_frame_size != | 
 |           pending_visual_properties_.local_frame_size || | 
 |       sent_visual_properties_->screen_space_rect.size() != | 
 |           pending_visual_properties_.screen_space_rect.size() || | 
 |       sent_visual_properties_->screen_info != | 
 |           pending_visual_properties_.screen_info || | 
 |       sent_visual_properties_->zoom_level != | 
 |           pending_visual_properties_.zoom_level || | 
 |       capture_sequence_number_changed; | 
 |  | 
 |   if (synchronized_props_changed) | 
 |     parent_local_surface_id_allocator_.GenerateId(); | 
 |  | 
 |   viz::SurfaceId surface_id(frame_sink_id_, GetLocalSurfaceId()); | 
 |   if (enable_surface_synchronization_) { | 
 |     // If we're synchronizing surfaces, then use an infinite deadline to ensure | 
 |     // everything is synchronized. | 
 |     cc::DeadlinePolicy deadline = | 
 |         capture_sequence_number_changed | 
 |             ? cc::DeadlinePolicy::UseInfiniteDeadline() | 
 |             : cc::DeadlinePolicy::UseDefaultDeadline(); | 
 |     compositing_helper_->SetPrimarySurfaceId(surface_id, local_frame_size(), | 
 |                                              deadline); | 
 |   } | 
 |  | 
 |   bool rect_changed = !sent_visual_properties_ || | 
 |                       sent_visual_properties_->screen_space_rect != | 
 |                           pending_visual_properties_.screen_space_rect; | 
 |   bool visual_properties_changed = synchronized_props_changed || rect_changed; | 
 |  | 
 | #if defined(USE_AURA) | 
 |   if (rect_changed && mus_embedded_frame_) { | 
 |     mus_embedded_frame_->SetWindowBounds(GetLocalSurfaceId(), | 
 |                                          gfx::Rect(local_frame_size())); | 
 |   } | 
 | #endif | 
 |  | 
 |   if (!visual_properties_changed) | 
 |     return; | 
 |  | 
 |   // Let the browser know about the updated view rect. | 
 |   Send(new FrameHostMsg_SynchronizeVisualProperties( | 
 |       routing_id_, surface_id, pending_visual_properties_)); | 
 |   sent_visual_properties_ = pending_visual_properties_; | 
 |  | 
 |   // The visible rect that the OOPIF needs to raster depends partially on | 
 |   // parameters that might have changed. If they affect the raster area, resend | 
 |   // the intersection rects. | 
 |   gfx::Rect new_compositor_visible_rect = web_frame_->GetCompositingRect(); | 
 |   if (new_compositor_visible_rect != last_compositor_visible_rect_) | 
 |     UpdateRemoteViewportIntersection(last_intersection_rect_); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnSetHasReceivedUserGestureBeforeNavigation(bool value) { | 
 |   web_frame_->SetHasReceivedUserGestureBeforeNavigation(value); | 
 | } | 
 |  | 
 | void RenderFrameProxy::FrameDetached(DetachType type) { | 
 | #if defined(USE_AURA) | 
 |   mus_embedded_frame_.reset(); | 
 | #endif | 
 |  | 
 |   if (type == DetachType::kRemove && web_frame_->Parent()) { | 
 |     // Let the browser process know this subframe is removed, so that it is | 
 |     // destroyed in its current process. | 
 |     Send(new FrameHostMsg_Detach(routing_id_)); | 
 |   } | 
 |  | 
 |   web_frame_->Close(); | 
 |  | 
 |   // If this proxy was associated with a provisional RenderFrame, and we're not | 
 |   // in the process of swapping with it, clean it up as well. | 
 |   if (type == DetachType::kRemove && | 
 |       provisional_frame_routing_id_ != MSG_ROUTING_NONE) { | 
 |     RenderFrameImpl* provisional_frame = | 
 |         RenderFrameImpl::FromRoutingID(provisional_frame_routing_id_); | 
 |     // |provisional_frame| should always exist.  If it was deleted via | 
 |     // FrameMsg_Delete right before this proxy was removed, | 
 |     // RenderFrameImpl::frameDetached would've cleared this proxy's | 
 |     // |provisional_frame_routing_id_| and we wouldn't get here. | 
 |     CHECK(provisional_frame); | 
 |     provisional_frame->GetWebFrame()->Detach(); | 
 |   } | 
 |  | 
 |   // Remove the entry in the WebFrame->RenderFrameProxy map, as the |web_frame_| | 
 |   // is no longer valid. | 
 |   FrameProxyMap::iterator it = g_frame_proxy_map.Get().find(web_frame_); | 
 |   CHECK(it != g_frame_proxy_map.Get().end()); | 
 |   CHECK_EQ(it->second, this); | 
 |   g_frame_proxy_map.Get().erase(it); | 
 |  | 
 |   web_frame_ = nullptr; | 
 |  | 
 |   delete this; | 
 | } | 
 |  | 
 | void RenderFrameProxy::CheckCompleted() { | 
 |   Send(new FrameHostMsg_CheckCompleted(routing_id_)); | 
 | } | 
 |  | 
 | void RenderFrameProxy::ForwardPostMessage( | 
 |     blink::WebLocalFrame* source_frame, | 
 |     blink::WebRemoteFrame* target_frame, | 
 |     blink::WebSecurityOrigin target_origin, | 
 |     blink::WebDOMMessageEvent event, | 
 |     bool has_user_gesture) { | 
 |   DCHECK(!web_frame_ || web_frame_ == target_frame); | 
 |  | 
 |   FrameMsg_PostMessage_Params params; | 
 |   params.message = | 
 |       new base::RefCountedData<blink::TransferableMessage>(event.AsMessage()); | 
 |   params.message->data.has_user_gesture = has_user_gesture; | 
 |   params.source_origin = event.Origin().Utf16(); | 
 |   if (!target_origin.IsNull()) | 
 |     params.target_origin = target_origin.ToString().Utf16(); | 
 |  | 
 |   // Include the routing ID for the source frame (if one exists), which the | 
 |   // browser process will translate into the routing ID for the equivalent | 
 |   // frame in the target process. | 
 |   params.source_routing_id = MSG_ROUTING_NONE; | 
 |   if (source_frame) { | 
 |     RenderFrameImpl* source_render_frame = | 
 |         RenderFrameImpl::FromWebFrame(source_frame); | 
 |     if (source_render_frame) | 
 |       params.source_routing_id = source_render_frame->GetRoutingID(); | 
 |   } | 
 |  | 
 |   Send(new FrameHostMsg_RouteMessageEvent(routing_id_, params)); | 
 | } | 
 |  | 
 | void RenderFrameProxy::Navigate(const blink::WebURLRequest& request, | 
 |                                 bool should_replace_current_entry, | 
 |                                 mojo::ScopedMessagePipeHandle blob_url_token) { | 
 |   FrameHostMsg_OpenURL_Params params; | 
 |   params.url = request.Url(); | 
 |   params.uses_post = request.HttpMethod().Utf8() == "POST"; | 
 |   params.resource_request_body = GetRequestBodyForWebURLRequest(request); | 
 |   params.extra_headers = GetWebURLRequestHeadersAsString(request); | 
 |   // TODO(domfarolino): Retrieve the referrer in the form of a referrer member | 
 |   // instead of the header field. See https://crbug.com/850813. | 
 |   params.referrer = Referrer(blink::WebStringToGURL(request.HttpHeaderField( | 
 |                                  blink::WebString::FromUTF8("Referer"))), | 
 |                              request.GetReferrerPolicy()); | 
 |   params.disposition = WindowOpenDisposition::CURRENT_TAB; | 
 |   params.should_replace_current_entry = should_replace_current_entry; | 
 |   params.user_gesture = request.HasUserGesture(); | 
 |   params.triggering_event_info = blink::WebTriggeringEventInfo::kUnknown; | 
 |   params.blob_url_token = blob_url_token.release(); | 
 |  | 
 |   Send(new FrameHostMsg_OpenURL(routing_id_, params)); | 
 | } | 
 |  | 
 | void RenderFrameProxy::FrameRectsChanged( | 
 |     const blink::WebRect& local_frame_rect, | 
 |     const blink::WebRect& screen_space_rect) { | 
 |   pending_visual_properties_.screen_space_rect = gfx::Rect(screen_space_rect); | 
 |   pending_visual_properties_.local_frame_size = | 
 |       gfx::Size(local_frame_rect.width, local_frame_rect.height); | 
 |   pending_visual_properties_.screen_info = | 
 |       render_widget_->GetOriginalScreenInfo(); | 
 |   if (crashed_) { | 
 |     // Update the sad page to match the current size. | 
 |     compositing_helper_->ChildFrameGone(local_frame_size(), | 
 |                                         screen_info().device_scale_factor); | 
 |     return; | 
 |   } | 
 |   SynchronizeVisualProperties(); | 
 | } | 
 |  | 
 | void RenderFrameProxy::UpdateRemoteViewportIntersection( | 
 |     const blink::WebRect& viewport_intersection) { | 
 |   last_intersection_rect_ = viewport_intersection; | 
 |   last_compositor_visible_rect_ = web_frame_->GetCompositingRect(); | 
 |   Send(new FrameHostMsg_UpdateViewportIntersection( | 
 |       routing_id_, gfx::Rect(viewport_intersection), | 
 |       last_compositor_visible_rect_)); | 
 | } | 
 |  | 
 | void RenderFrameProxy::VisibilityChanged(bool visible) { | 
 |   Send(new FrameHostMsg_VisibilityChanged(routing_id_, visible)); | 
 | } | 
 |  | 
 | void RenderFrameProxy::SetIsInert(bool inert) { | 
 |   Send(new FrameHostMsg_SetIsInert(routing_id_, inert)); | 
 | } | 
 |  | 
 | void RenderFrameProxy::SetInheritedEffectiveTouchAction( | 
 |     cc::TouchAction touch_action) { | 
 |   Send(new FrameHostMsg_SetInheritedEffectiveTouchAction(routing_id_, | 
 |                                                          touch_action)); | 
 | } | 
 |  | 
 | void RenderFrameProxy::UpdateRenderThrottlingStatus(bool is_throttled, | 
 |                                                     bool subtree_throttled) { | 
 |   Send(new FrameHostMsg_UpdateRenderThrottlingStatus(routing_id_, is_throttled, | 
 |                                                      subtree_throttled)); | 
 | } | 
 |  | 
 | void RenderFrameProxy::DidChangeOpener(blink::WebFrame* opener) { | 
 |   // A proxy shouldn't normally be disowning its opener.  It is possible to get | 
 |   // here when a proxy that is being detached clears its opener, in which case | 
 |   // there is no need to notify the browser process. | 
 |   if (!opener) | 
 |     return; | 
 |  | 
 |   // Only a LocalFrame (i.e., the caller of window.open) should be able to | 
 |   // update another frame's opener. | 
 |   DCHECK(opener->IsWebLocalFrame()); | 
 |  | 
 |   int opener_routing_id = | 
 |       RenderFrameImpl::FromWebFrame(opener->ToWebLocalFrame())->GetRoutingID(); | 
 |   Send(new FrameHostMsg_DidChangeOpener(routing_id_, opener_routing_id)); | 
 | } | 
 |  | 
 | void RenderFrameProxy::AdvanceFocus(blink::WebFocusType type, | 
 |                                     blink::WebLocalFrame* source) { | 
 |   int source_routing_id = RenderFrameImpl::FromWebFrame(source)->GetRoutingID(); | 
 |   Send(new FrameHostMsg_AdvanceFocus(routing_id_, type, source_routing_id)); | 
 | } | 
 |  | 
 | void RenderFrameProxy::FrameFocused() { | 
 |   Send(new FrameHostMsg_FrameFocused(routing_id_)); | 
 | } | 
 |  | 
 | base::UnguessableToken RenderFrameProxy::GetDevToolsFrameToken() { | 
 |   return devtools_frame_token_; | 
 | } | 
 |  | 
 | #if defined(USE_AURA) | 
 | void RenderFrameProxy::OnMusEmbeddedFrameSurfaceChanged( | 
 |     const viz::SurfaceInfo& surface_info) { | 
 |   OnFirstSurfaceActivation(surface_info); | 
 | } | 
 |  | 
 | void RenderFrameProxy::OnMusEmbeddedFrameSinkIdAllocated( | 
 |     const viz::FrameSinkId& frame_sink_id) { | 
 |   // RendererWindowTreeClient should only call this when mus is hosting viz. | 
 |   DCHECK(!features::IsAshInBrowserProcess()); | 
 |   frame_sink_id_ = frame_sink_id; | 
 |   // Resend the FrameRects and allocate a new viz::LocalSurfaceId when the view | 
 |   // changes. | 
 |   ResendVisualProperties(); | 
 | } | 
 | #endif | 
 |  | 
 | cc::Layer* RenderFrameProxy::GetLayer() { | 
 |   return embedded_layer_.get(); | 
 | } | 
 |  | 
 | void RenderFrameProxy::SetLayer(scoped_refptr<cc::Layer> layer, | 
 |                                 bool prevent_contents_opaque_changes) { | 
 |   if (web_frame()) | 
 |     web_frame()->SetCcLayer(layer.get(), prevent_contents_opaque_changes); | 
 |   embedded_layer_ = std::move(layer); | 
 | } | 
 |  | 
 | SkBitmap* RenderFrameProxy::GetSadPageBitmap() { | 
 |   return GetContentClient()->renderer()->GetSadWebViewBitmap(); | 
 | } | 
 |  | 
 | uint32_t RenderFrameProxy::Print(const blink::WebRect& rect, | 
 |                                  cc::PaintCanvas* canvas) { | 
 | #if BUILDFLAG(ENABLE_PRINTING) | 
 |   printing::PdfMetafileSkia* metafile = | 
 |       printing::MetafileSkiaWrapper::GetMetafileFromCanvas(canvas); | 
 |   DCHECK(metafile); | 
 |  | 
 |   // Create a place holder content for the remote frame so it can be replaced | 
 |   // with actual content later. | 
 |   uint32_t content_id = | 
 |       metafile->CreateContentForRemoteFrame(rect, routing_id_); | 
 |  | 
 |   // Inform browser to print the remote subframe. | 
 |   Send(new FrameHostMsg_PrintCrossProcessSubframe( | 
 |       routing_id_, rect, metafile->GetDocumentCookie())); | 
 |   return content_id; | 
 | #else | 
 |   return 0; | 
 | #endif | 
 | } | 
 |  | 
 | const viz::LocalSurfaceId& RenderFrameProxy::GetLocalSurfaceId() const { | 
 |   return parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId(); | 
 | } | 
 |  | 
 | }  // namespace content |