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_
|