File: guest_view_manager.h

package info (click to toggle)
chromium 138.0.7204.157-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,864 kB
  • sloc: cpp: 34,936,859; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,967; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (334 lines) | stat: -rw-r--r-- 13,991 bytes parent folder | download | duplicates (4)
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
// 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 COMPONENTS_GUEST_VIEW_BROWSER_GUEST_VIEW_MANAGER_H_
#define COMPONENTS_GUEST_VIEW_BROWSER_GUEST_VIEW_MANAGER_H_

#include <map>
#include <memory>
#include <set>
#include <vector>

#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/values.h"
#include "content/public/browser/browser_plugin_guest_manager.h"
#include "content/public/browser/child_process_id.h"
#include "content/public/browser/frame_tree_node_id.h"
#include "content/public/browser/guest_page_holder.h"
#include "content/public/browser/web_contents.h"

namespace content {
class BrowserContext;
class NavigationHandle;
class SiteInstance;
class StoragePartitionConfig;
}

namespace guest_view {

class GuestViewBase;
class GuestViewManagerDelegate;
class GuestViewManagerFactory;

class GuestViewManager : public content::BrowserPluginGuestManager,
                         public base::SupportsUserData::Data {
 public:
  GuestViewManager(content::BrowserContext* context,
                   std::unique_ptr<GuestViewManagerDelegate> delegate);

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

  ~GuestViewManager() override;

  // Returns the GuestViewManager associated with |context|. If one isn't
  // available, then it is created and returned.
  static GuestViewManager* CreateWithDelegate(
      content::BrowserContext* context,
      std::unique_ptr<GuestViewManagerDelegate> delegate);

  // Returns the GuestViewManager associated with |context|. If one isn't
  // available, then nullptr is returned.
  static GuestViewManager* FromBrowserContext(content::BrowserContext* context);

  // Overrides factory for testing. Default (NULL) value indicates regular
  // (non-test) environment.
  static void set_factory_for_testing(GuestViewManagerFactory* factory);

  // Returns the guest associated with the given |guest_instance_id|
  // if the provided |embedder_render_process_id| is allowed to access it.
  // If the embedder is not allowed access, the embedder will be killed, and
  // this method will return NULL. If no guest exists with the given
  // instance ID, then NULL will also be returned.
  GuestViewBase* GetGuestByInstanceIDSafely(
      int guest_instance_id,
      content::ChildProcessId embedder_render_process_id);
  // TODO(crbug.com/379869738): Deprecated, please use the ChildProcessId
  // version above.
  GuestViewBase* GetGuestByInstanceIDSafely(int guest_instance_id,
                                            int embedder_render_process_id);

  // Associates the Browser Plugin with |element_instance_id| to a
  // guest that has ID of |guest_instance_id| and sets initialization
  // parameters, |params| for it.
  virtual void AttachGuest(content::ChildProcessId embedder_process_id,
                           int element_instance_id,
                           int guest_instance_id,
                           const base::Value::Dict& attach_params);
  // TODO(crbug.com/379869738): Deprecated, please use the ChildProcessId
  // version above.
  virtual void AttachGuest(int embedder_process_id,
                           int element_instance_id,
                           int guest_instance_id,
                           const base::Value::Dict& attach_params);

  // Indicates whether the |guest| is owned by an extension or Chrome App.
  bool IsOwnedByExtension(const GuestViewBase* guest);

  // Indicates whether the |guest| is owned by a Controlled Frame embedder.
  bool IsOwnedByControlledFrameEmbedder(const GuestViewBase* guest);

  int GetNextInstanceID();

  base::WeakPtr<GuestViewManager> AsWeakPtr();

  using GuestViewCreateFunction =
      base::RepeatingCallback<std::unique_ptr<GuestViewBase>(
          content::RenderFrameHost* owner_rfh)>;
  using GuestViewCleanUpFunction =
      base::RepeatingCallback<void(content::BrowserContext*,
                                   content::ChildProcessId embedder_process_id,
                                   int view_instance_id)>;
  void RegisterGuestViewType(const std::string& type,
                             GuestViewCreateFunction create_function,
                             GuestViewCleanUpFunction cleanup_function);

  // Registers a callback to be called when the view identified by
  // |embedder_process_id| and |view_instance_id| is destroyed.
  // Note that multiple callbacks can be registered for one view.
  void RegisterViewDestructionCallback(
      content::ChildProcessId embedder_process_id,
      int view_instance_id,
      base::OnceClosure callback);
  // TODO(crbug.com/379869738): Deprecated, please use the ChildProcessId
  // version above.
  void RegisterViewDestructionCallback(int embedder_process_id,
                                       int view_instance_id,
                                       base::OnceClosure callback);

  using UnownedGuestCreatedCallback = base::OnceCallback<void(GuestViewBase*)>;
  using OwnedGuestCreatedCallback =
      base::OnceCallback<void(std::unique_ptr<GuestViewBase>)>;
  // Creates a guest and has the GuestViewManager assume ownership.
  void CreateGuest(const std::string& view_type,
                   content::RenderFrameHost* owner_rfh,
                   const base::Value::Dict& create_params,
                   UnownedGuestCreatedCallback callback);
  // Creates a guest which the caller will own.
  int CreateGuestAndTransferOwnership(
      const std::string& view_type,
      content::RenderFrameHost* owner_rfh,
      scoped_refptr<content::SiteInstance> site_instance,
      const base::Value::Dict& create_params,
      OwnedGuestCreatedCallback callback);

  // Transfers ownership of `guest` to the caller.
  std::unique_ptr<GuestViewBase> TransferOwnership(GuestViewBase* guest);
  // Have `this` manage ownership of `guest`.
  void ManageOwnership(std::unique_ptr<GuestViewBase> guest);

  std::unique_ptr<content::WebContents> CreateGuestWithWebContentsParams(
      const std::string& view_type,
      content::RenderFrameHost* owner_rfh,
      const content::WebContents::CreateParams& create_params);

  content::SiteInstance* GetGuestSiteInstance(
      const content::StoragePartitionConfig& storage_partition_config);

  // BrowserPluginGuestManager implementation.
  void ForEachUnattachedGuestContents(
      content::WebContents* owner_web_contents,
      base::FunctionRef<void(content::WebContents*)> fn) override;
  void ForEachUnattachedGuestPage(
      content::Page& owner_page,
      base::FunctionRef<void(content::GuestPageHolder&)> fn) override;
  bool ForEachGuest(content::WebContents* owner_web_contents,
                    base::FunctionRef<bool(content::WebContents*)> fn) override;
  content::WebContents* GetFullPageGuest(
      content::WebContents* embedder_web_contents) override;

 protected:
  friend class GuestViewBase;
  friend class GuestViewEvent;
  friend class GuestViewMessageHandler;
  friend class ViewHandle;

  class EmbedderRenderProcessHostObserver;

  // These methods are virtual so that they can be overriden in tests.

  virtual void AddGuest(GuestViewBase* guest);
  // If a GuestView is created but never initialized with a guest WebContents,
  // this should still be called to invalidate `guest`'s `guest_instance_id`.
  // If `invalidate_id` is false, then the id may be reused to associate a guest
  // with a new guest WebContents.
  void RemoveGuest(GuestViewBase* guest, bool invalidate_id);

  GuestViewBase* GetGuestFromWebContents(content::WebContents* web_contents);
  GuestViewBase* GetGuestFromRenderFrameHost(content::RenderFrameHost& rfh);
  GuestViewBase* GetGuestFromNavigationHandle(
      content::NavigationHandle& navigation_handle);
  GuestViewBase* GetGuestFromFrameTreeNodeId(
      content::FrameTreeNodeId frame_tree_node_id);

  GuestViewBase* GetGuestFromOutermostFrameTreeNodeId(
      content::FrameTreeNodeId outermost_ftn_id);

  // This method is called when the embedder process with ID
  // |embedder_process_id| has been destroyed.
  virtual void EmbedderProcessDestroyed(
      content::ChildProcessId embedder_process_id);

  // Called when a GuestView has been created in JavaScript.
  virtual void ViewCreated(content::ChildProcessId embedder_process_id,
                           int view_instance_id,
                           const std::string& view_type);

  // Called when a GuestView has been garbage collected in JavaScript.
  virtual void ViewGarbageCollected(content::ChildProcessId embedder_process_id,
                                    int view_instance_id);

  // Calls all destruction callbacks registered for the GuestView identified by
  // |embedder_process_id| and |view_instance_id|.
  void CallViewDestructionCallbacks(content::ChildProcessId embedder_process_id,
                                    int view_instance_id);

  // Calls all destruction callbacks registered for GuestViews in the embedder
  // with ID |embedder_process_id|.
  void CallViewDestructionCallbacks(
      content::ChildProcessId embedder_process_id);

  // Creates a guest of the provided |view_type|.
  std::unique_ptr<GuestViewBase> CreateGuestInternal(
      content::RenderFrameHost* owner_rfh,
      const std::string& view_type);

  // Adds GuestView types to the GuestView registry.
  void RegisterGuestViewTypes();

  // Starts observing an embedder process's lifetime.
  void ObserveEmbedderLifetime(content::RenderProcessHost* embedder_process);

  // Indicates whether the provided |guest| can be used in the context it has
  // been created.
  bool IsGuestAvailableToContext(GuestViewBase* guest);

  // Dispatches the event with |name| with the provided |args| to the embedder
  // of the given |guest| with |instance_id| for routing.
  void DispatchEvent(const std::string& event_name,
                     base::Value::Dict args,
                     GuestViewBase* guest,
                     int instance_id);

  GuestViewBase* GetGuestByInstanceID(int guest_instance_id);

  bool CanEmbedderAccessInstanceIDMaybeKill(
      content::ChildProcessId embedder_render_process_id,
      int guest_instance_id);

  bool CanEmbedderAccessInstanceID(
      content::ChildProcessId embedder_render_process_id,
      int guest_instance_id);

  // Returns true if |guest_instance_id| can be used to add a new guest to this
  // manager.
  // We disallow adding new guest with instance IDs that were previously removed
  // from this manager using RemoveGuest.
  bool CanUseGuestInstanceID(int guest_instance_id);

  // Contains guests, mapping from their instance ids.
  using GuestInstanceMap =
      std::map<int, raw_ptr<GuestViewBase, CtnExperimental>>;
  GuestInstanceMap guests_by_instance_id_;

  using WebContentsGuestViewMap =
      std::map<const content::WebContents*,
               raw_ptr<GuestViewBase, CtnExperimental>>;
  WebContentsGuestViewMap webcontents_guestview_map_;

  // Maps the FTN ID of a guest's main frame to the associated `GuestViewBase`.
  std::map<content::FrameTreeNodeId, GuestViewBase*>
      guest_page_frame_id_guestview_map_;

  struct ElementInstanceKey {
    content::ChildProcessId embedder_process_id;
    int element_instance_id;

    ElementInstanceKey();
    ElementInstanceKey(content::ChildProcessId embedder_process_id,
                       int element_instance_id);

    bool operator<(const ElementInstanceKey& other) const;
  };

  using GuestInstanceIDMap = std::map<ElementInstanceKey, int>;
  GuestInstanceIDMap instance_id_map_;

  // The reverse map of GuestInstanceIDMap.
  using GuestInstanceIDReverseMap = std::map<int, ElementInstanceKey>;
  GuestInstanceIDReverseMap reverse_instance_id_map_;

  struct GuestViewData {
    GuestViewData(const GuestViewCreateFunction& create_function,
                  const GuestViewCleanUpFunction& cleanup_function);
    GuestViewData(const GuestViewData& other);
    ~GuestViewData();
    const GuestViewCreateFunction create_function;
    const GuestViewCleanUpFunction cleanup_function;
  };
  using GuestViewMethodMap = std::map<std::string, GuestViewData>;
  GuestViewMethodMap guest_view_registry_;

  int current_instance_id_ = 0;

  // Any instance ID whose number not greater than this was removed via
  // RemoveGuest.
  // This is used so that we don't have store all removed instance IDs in
  // |removed_instance_ids_|.
  int last_instance_id_removed_ = 0;
  // The remaining instance IDs that are greater than
  // |last_instance_id_removed_| are kept here.
  std::set<int> removed_instance_ids_;

  const raw_ptr<content::BrowserContext> context_;

  std::unique_ptr<GuestViewManagerDelegate> delegate_;

  // This tracks which GuestView embedders are currently being observed.
  std::set<content::ChildProcessId> embedders_observed_;

  // Maps embedder process ids to unattached guests whose lifetimes are being
  // managed by this GuestViewManager. An unattached guest's lifetime is scoped
  // to the process that created it by this manager. Ownership is taken from
  // this manager via `TransferOwnership` upon guest attachment, or for cases
  // where an unattached guest needs to be destroyed earlier.
  std::multimap<content::ChildProcessId, std::unique_ptr<GuestViewBase>>
      owned_guests_;

  // |view_destruction_callback_map_| maps from embedder process ID to view ID
  // to a vector of callback functions to be called when that view is destroyed.
  using Callbacks = std::vector<base::OnceClosure>;
  using CallbacksForEachViewID = std::map<int, Callbacks>;
  using CallbacksForEachEmbedderID =
      std::map<content::ChildProcessId, CallbacksForEachViewID>;
  CallbacksForEachEmbedderID view_destruction_callback_map_;

  base::WeakPtrFactory<GuestViewManager> weak_ptr_factory_{this};
};

}  // namespace guest_view

#endif  // COMPONENTS_GUEST_VIEW_BROWSER_GUEST_VIEW_MANAGER_H_