1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
  222
  223
  224
  225
  226
  227
  228
  229
  230
  231
  232
  233
  234
  235
  236
  237
  238
  239
  240
  241
  242
  243
  244
  245
  246
  247
  248
  249
  250
  251
  252
  253
  254
  255
  256
  257
  258
  259
  260
  261
  262
  263
  264
  265
  266
  267
  268
  269
  270
  271
  272
  273
  274
  275
  276
  277
  278
  279
  280
  281
  282
  283
  284
  285
  286
  287
  288
  289
  290
  291
  292
  293
  294
  295
  296
  297
  298
  299
  300
  301
  302
  303
  304
  305
  306
  307
  308
  309
  310
  311
  312
  313
  314
  315
  316
  317
  318
  319
  320
  321
  322
  323
  324
  325
  326
  327
  328
  329
  330
  331
  332
  333
  334
  335
  336
  337
  338
  339
  340
  341
  342
  343
  344
  345
  346
  347
  348
  349
  350
  351
  352
  353
  354
  355
  356
  357
  358
  359
  360
  361
  362
  363
  364
  365
  366
  367
  368
  369
  370
  371
  372
  373
  374
  375
  376
  377
  378
  379
  380
  381
  382
  383
  384
  385

content / browser / renderer_host / render_frame_proxy_host.h [blame]

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_BROWSER_RENDERER_HOST_RENDER_FRAME_PROXY_HOST_H_
#define CONTENT_BROWSER_RENDERER_HOST_RENDER_FRAME_PROXY_HOST_H_

#include <stdint.h>

#include <memory>

#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/safe_ref.h"
#include "content/browser/renderer_host/agent_scheduling_group_host.h"
#include "content/browser/site_instance_impl.h"
#include "content/common/content_export.h"
#include "content/common/frame.mojom.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/render_process_host.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/frame/frame.mojom.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-forward.h"
#include "third_party/blink/public/mojom/messaging/transferable_message.mojom-forward.h"
#include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-forward.h"

namespace blink {
class AssociatedInterfaceProvider;
}

namespace gfx {
class Rect;
class RectF;
}

namespace perfetto {
namespace protos {
namespace pbzero {
class RenderFrameProxyHost;
}
}  // namespace protos
}  // namespace perfetto

namespace content {

class BatchedProxyIPCSender;
class CrossProcessFrameConnector;
class FrameTreeNode;
class RenderViewHostImpl;
class RenderWidgetHostViewChildFrame;
class SiteInstanceGroup;

// When a page's frames are rendered by multiple processes, each renderer has a
// full copy of the frame tree. It has full RenderFrames for the frames it is
// responsible for rendering and placeholder objects (i.e.,
// `blink::RemoteFrame`) for frames rendered by other processes.
//
// This class is the browser-side host object for the placeholder. Each node in
// the frame tree has a RenderFrameHost for the active SiteInstance and a set
// of RenderFrameProxyHost objects - one for all other SiteInstanceGroups with
// references to this frame. The proxies allow us to keep existing window
// references valid over cross-process navigations and route cross-site
// asynchronous JavaScript calls, such as postMessage.
//
// RenderFrameProxyHost is created whenever a cross-site
// navigation occurs and a reference to the frame navigating needs to be kept
// alive. A RenderFrameProxyHost and a RenderFrameHost in the same
// SiteInstanceGroup can exist at the same time, but only one will be "active"
// at a time. There are two cases where the two objects will coexist:
// * When navigating cross-process and there is already a RenderFrameProxyHost
// for the new SiteInstanceGroup. A pending RenderFrameHost is created, but it
// is not used until it commits. At that point, RenderFrameHostManager
// transitions the pending RenderFrameHost to the active one and deletes the
// proxy.
// * When navigating cross-process and the existing document has an unload
// event handler. When the new navigation commits, RenderFrameHostManager
// creates a RenderFrameProxyHost for the old SiteInstanceGroup and uses it
// going forward. It also instructs the RenderFrameHost to run the unload event
// handler and is kept alive for the duration. Once the event handling is
// complete, the RenderFrameHost is deleted.
class CONTENT_EXPORT RenderFrameProxyHost
    : public IPC::Listener,
      public IPC::Sender,
      public blink::mojom::RemoteFrameHost,
      public blink::mojom::RemoteMainFrameHost {
 public:
  // A test observer to monitor RenderFrameProxyHosts.
  class TestObserver {
   public:
    virtual ~TestObserver() = default;
    // Called when a RenderFrameProxyHost is created.
    virtual void OnCreated(RenderFrameProxyHost* host) {}
    // Called when a RenderFrameProxyHost is deleted.
    virtual void OnDeleted(RenderFrameProxyHost* host) {}
    // Called when Remote/RemoteMainFrame mojo channels are bound to a
    // RenderFrameProxyHost.
    virtual void OnRemoteFrameBound(RenderFrameProxyHost* host) {}
    virtual void OnRemoteMainFrameBound(RenderFrameProxyHost* host) {}
  };

  static void SetObserverForTesting(TestObserver* observer);

  static RenderFrameProxyHost* FromID(int process_id, int routing_id);
  static RenderFrameProxyHost* FromFrameToken(
      int process_id,
      const blink::RemoteFrameToken& frame_token);
  static bool IsFrameTokenInUse(const blink::RemoteFrameToken& frame_token);

  RenderFrameProxyHost(SiteInstanceGroup* site_instance_group,
                       scoped_refptr<RenderViewHostImpl> render_view_host,
                       FrameTreeNode* frame_tree_node,
                       const blink::RemoteFrameToken& frame_token);

  RenderFrameProxyHost(const RenderFrameProxyHost&) = delete;
  RenderFrameProxyHost& operator=(const RenderFrameProxyHost&) = delete;

  ~RenderFrameProxyHost() override;

  RenderProcessHost* GetProcess() const { return process_; }

  // Initializes the object and creates the `blink::RemoteFrame` in the process
  // for the `site_instance_group_`. If `batched_proxy_ipc_sender` is not null,
  // then the proxy will not be created immediately. It will be batch created
  // later.
  bool InitRenderFrameProxy(
      BatchedProxyIPCSender* batched_proxy_ipc_sender = nullptr);

  int GetRoutingID() const { return routing_id_; }
  GlobalRoutingID GetGlobalID() const {
    return GlobalRoutingID(GetProcess()->GetID(), routing_id_);
  }

  // Each RenderFrameProxyHost belongs to a SiteInstanceGroup, where it is a
  // placeholder for a frame in a different SiteInstanceGroup.
  SiteInstanceGroup* site_instance_group() const {
    return site_instance_group_.get();
  }

  // TODO(crbug.com/40169570): FrameTree and FrameTreeNode are not const
  // as with prerenderer activation the page needs to move between
  // FrameTreeNodes and FrameTrees. Note that FrameTreeNode can only change for
  // root nodes. As it's hard to make sure that all places handle this
  // transition correctly, MPArch will remove references from this class to
  // FrameTree/FrameTreeNode.
  FrameTreeNode* frame_tree_node() const { return frame_tree_node_; }

  void set_frame_tree_node(FrameTreeNode& frame_tree_node) {
    frame_tree_node_ = &frame_tree_node;
  }

  // Associates the RenderWidgetHostViewChildFrame |view| with this
  // RenderFrameProxyHost. If |initial_frame_size| isn't specified at this time,
  // the child frame will wait until the CrossProcessFrameConnector
  // receives its size from the parent via FrameHostMsg_UpdateResizeParams
  // before it begins parsing the content.
  void SetChildRWHView(RenderWidgetHostViewChildFrame* view,
                       const gfx::Size* initial_frame_size,
                       bool allow_paint_holding);

  RenderViewHostImpl* GetRenderViewHost();

  // IPC::Sender
  bool Send(IPC::Message* msg) override;

  // IPC::Listener
  bool OnMessageReceived(const IPC::Message& msg) override;
  std::string ToDebugString() override;

  CrossProcessFrameConnector* cross_process_frame_connector() {
    return cross_process_frame_connector_.get();
  }

  // Update the frame's opener in the renderer process in response to the
  // opener being modified (e.g., with window.open or being set to null) in
  // another renderer process.
  void UpdateOpener();

  // Set this proxy as the focused frame in the renderer process.  This is
  // called to replicate the focused frame when a frame in a different process
  // becomes focused.
  void SetFocusedFrame();

  // Scroll |rect_to_scroll| into view, starting from this proxy's FrameOwner
  // element in the frame's parent. Calling this continues a scroll started in
  // the frame's current process. |rect_to_scroll| is with respect to the
  // coordinates of the originating frame in OOPIF process.
  void ScrollRectToVisible(const gfx::RectF& rect_to_scroll,
                           blink::mojom::ScrollIntoViewParamsPtr params);

  // Sets render frame proxy created state. If |created| is false, any existing
  // mojo connections to RenderFrameProxyHost will be closed.
  void SetRenderFrameProxyCreated(bool created);

  // Returns if the `blink::RemoteFrame` for this host is alive.
  bool is_render_frame_proxy_live() const {
    return render_frame_proxy_created_;
  }

  // Returns associated remote for the blink::mojom::RemoteFrame Mojo interface.
  const mojo::AssociatedRemote<blink::mojom::RemoteFrame>&
  GetAssociatedRemoteFrame();

  // Returns associated remote for the blink::mojom::RemoteMainFrame Mojo
  // interface.
  const mojo::AssociatedRemote<blink::mojom::RemoteMainFrame>&
  GetAssociatedRemoteMainFrame();

  // blink::mojom::RemoteFrameHost
  void SetInheritedEffectiveTouchAction(cc::TouchAction touch_action) override;
  void UpdateRenderThrottlingStatus(bool is_throttled,
                                    bool subtree_throttled,
                                    bool display_locked) override;
  void VisibilityChanged(blink::mojom::FrameVisibility visibility) override;
  void DidFocusFrame() override;
  void CheckCompleted() override;
  void CapturePaintPreviewOfCrossProcessSubframe(
      const gfx::Rect& clip_rect,
      const base::UnguessableToken& guid) override;
  void SetIsInert(bool inert) override;
  void DidChangeOpener(
      const std::optional<blink::LocalFrameToken>& opener_frame_token) override;
  void AdvanceFocus(blink::mojom::FocusType focus_type,
                    const blink::LocalFrameToken& source_frame_token) override;
  void RouteMessageEvent(
      const std::optional<blink::LocalFrameToken>& source_frame_token,
      const url::Origin& source_origin,
      const std::u16string& target_origin,
      blink::TransferableMessage message) override;
  void PrintCrossProcessSubframe(const gfx::Rect& rect,
                                 int document_cookie) override;
  void Detach() override;
  void UpdateViewportIntersection(
      blink::mojom::ViewportIntersectionStatePtr intersection_state,
      const std::optional<blink::FrameVisualProperties>& visual_properties)
      override;
  void SynchronizeVisualProperties(
      const blink::FrameVisualProperties& frame_visual_properties) override;
  void OpenURL(blink::mojom::OpenURLParamsPtr params) override;

  // blink::mojom::RemoteMainFrameHost overrides:
  void FocusPage() override;
  void TakeFocus(bool reverse) override;
  void UpdateTargetURL(
      const GURL& url,
      blink::mojom::RemoteMainFrameHost::UpdateTargetURLCallback callback)
      override;
  void RouteCloseEvent() override;

  // Requests a viz::LocalSurfaceId to enable auto-resize mode from the parent
  // renderer.
  void EnableAutoResize(const gfx::Size& min_size, const gfx::Size& max_size);
  // Requests a viz::LocalSurfaceId to disable auto-resize mode from the parent
  // renderer.
  void DisableAutoResize();
  void DidUpdateVisualProperties(const cc::RenderFrameMetadata& metadata);
  void ChildProcessGone();

  bool IsInertForTesting();

  mojo::PendingAssociatedReceiver<blink::mojom::RemoteFrame>
  BindRemoteFrameReceiverForTesting();
  mojo::PendingAssociatedReceiver<blink::mojom::RemoteMainFrame>
  BindRemoteMainFrameReceiverForTesting();

  const blink::RemoteFrameToken& GetFrameToken() const { return frame_token_; }

  // Bind mojo endpoints of the Remote/RemoteMainFrame in blink and pass unbound
  // corresponding endpoints. The corresponding endpoints should be transferred
  // and bound in blink.
  blink::mojom::RemoteFrameInterfacesFromBrowserPtr
  CreateAndBindRemoteFrameInterfaces();
  blink::mojom::RemoteMainFrameInterfacesPtr
  CreateAndBindRemoteMainFrameInterfaces();

  // Bind mojo endpoints of the Remote/RemoteMainFrame in blink.
  void BindRemoteFrameInterfaces(
      mojo::PendingAssociatedRemote<blink::mojom::RemoteFrame>,
      mojo::PendingAssociatedReceiver<blink::mojom::RemoteFrameHost>);
  void BindRemoteMainFrameInterfaces(
      mojo::PendingAssociatedRemote<blink::mojom::RemoteMainFrame>
          remote_main_frame,
      mojo::PendingAssociatedReceiver<blink::mojom::RemoteMainFrameHost>
          remote_main_frame_host_receiver);

  // Invalidate the mojo connections between this RenderFrameProxyHost and its
  // associated instances in renderer, allowing the endpoints to be re-bound.
  // This is needed when:
  // - the renderer side object goes away due to the renderer process going away
  //   (i.e. crashing)
  // - undoing a `CommitNavigation()` that has already been sent to a
  //   speculative RenderFrameHost by swapping it back to a
  //   `blink::RemoteFrame`.
  void TearDownMojoConnection();

  using TraceProto = perfetto::protos::pbzero::RenderFrameProxyHost;
  // Write a representation of this object into a trace.
  void WriteIntoTrace(perfetto::TracedProto<TraceProto> proto) const;

  base::SafeRef<RenderFrameProxyHost> GetSafeRef();

 private:
  // These interceptors need access to frame_host_receiver_for_testing().
  friend class InitiatorClosingOpenURLInterceptor;
  friend class RemoteFrameHostInterceptor;
  friend class UpdateViewportIntersectionMessageFilter;
  friend class SynchronizeVisualPropertiesInterceptor;

  // Helper to retrieve the |AgentSchedulingGroup| this proxy host is associated
  // with.
  AgentSchedulingGroupHost& GetAgentSchedulingGroup();

  // Helper to compute the serialized source origin from an actual source origin
  // for postMessage. This will ultimately be exposed to JavaScript via the
  // message's event.origin field.
  std::u16string SerializePostMessageSourceOrigin(
      const url::Origin& source_origin);

  // Needed for tests to be able to swap the implementation and intercept calls.
  mojo::AssociatedReceiver<blink::mojom::RemoteFrameHost>&
  frame_host_receiver_for_testing() {
    return remote_frame_host_receiver_;
  }

  // This RenderFrameProxyHost's routing id.
  int routing_id_;

  // The SiteInstanceGroup this RenderFrameProxyHost belongs to, where it is a
  // placeholder for a frame in a different SiteInstanceGroup.
  scoped_refptr<SiteInstanceGroup> site_instance_group_;

  // The renderer process this RenderFrameProxyHost is associated with. It is
  // equivalent to the result of site_instance_group_->GetProcess(), but that
  // method has the side effect of creating the process if it doesn't exist.
  // Cache a pointer to avoid unnecessary process creation.
  raw_ptr<RenderProcessHost> process_;

  // The node in the frame tree where this proxy is located.
  raw_ptr<FrameTreeNode> frame_tree_node_;

  // True if we have a live `blink::RemoteFrame` for this host.
  bool render_frame_proxy_created_;

  // When a RenderFrameHost is in a different process from its parent in the
  // frame tree, this class connects its associated RenderWidgetHostView
  // to this RenderFrameProxyHost, which corresponds to the same frame in the
  // parent's renderer process.
  std::unique_ptr<CrossProcessFrameConnector> cross_process_frame_connector_;

  // The RenderViewHost that this RenderFrameProxyHost is associated with.
  //
  // It is kept alive as long as any RenderFrameHosts or RenderFrameProxyHosts
  // are using it.
  //
  // TODO(creis): RenderViewHost will eventually go away and be replaced with
  // some form of page context.
  scoped_refptr<RenderViewHostImpl> render_view_host_;

  std::unique_ptr<blink::AssociatedInterfaceProvider>
      remote_associated_interfaces_;

  // Holder of Mojo connection with the Frame service in Blink.
  mojo::AssociatedRemote<blink::mojom::RemoteFrame> remote_frame_;

  // Holder of Mojo connection with the RemoteMainFrame in Blink. This remote
  // will be valid when the frame is the active main frame.
  mojo::AssociatedRemote<blink::mojom::RemoteMainFrame> remote_main_frame_;

  mojo::AssociatedReceiver<blink::mojom::RemoteFrameHost>
      remote_frame_host_receiver_{this};

  mojo::AssociatedReceiver<blink::mojom::RemoteMainFrameHost>
      remote_main_frame_host_receiver_{this};

  blink::RemoteFrameToken frame_token_;

  base::WeakPtrFactory<RenderFrameProxyHost> weak_factory_{this};
};

}  // namespace content

#endif  // CONTENT_BROWSER_RENDERER_HOST_RENDER_FRAME_PROXY_HOST_H_