summaryrefslogtreecommitdiff
path: root/chromium/components/guest_view/browser/guest_view_manager.h
blob: 84a8cda92a0f7f67576873429183540dcec17d17 (plain)
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
// 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.

#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/bind.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/public/browser/browser_plugin_guest_manager.h"
#include "content/public/browser/web_contents.h"

class GURL;

namespace base {
class DictionaryValue;
}

namespace content {
class BrowserContext;
class SiteInstance;
}

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() 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 WebContents 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 WebContents exists with the given
  // instance ID, then NULL will also be returned.
  content::WebContents* 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(int embedder_process_id,
                           int element_instance_id,
                           int guest_instance_id,
                           const base::DictionaryValue& attach_params);

  // Removes the association between |element_instance_id| and a guest instance
  // ID if one exists.
  void DetachGuest(GuestViewBase* guest);

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

  int GetNextInstanceID();
  int GetGuestInstanceIDForElementID(
      int owner_process_id,
      int element_instance_id);

  template <typename T>
  void RegisterGuestViewType() {
    // If the GuestView type |T| is already registered, then there is nothing
    // more to do. If an existing entry in the registry was created by this
    // function for type |T|, then registering again would have no effect, and
    // if it was registered elsewhere, then we do not want to overwrite it. Note
    // that it is possible for tests to have special test factory methods
    // registered here.
    if (guest_view_registry_.count(T::Type))
      return;
    auto registry_entry = std::make_pair(
        T::Type,
        GuestViewData(base::Bind(&T::Create), base::Bind(&T::CleanUp)));
    guest_view_registry_.insert(registry_entry);
  }

  // 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(int embedder_process_id,
                                       int view_instance_id,
                                       const base::Closure& callback);

  using WebContentsCreatedCallback =
      base::OnceCallback<void(content::WebContents*)>;
  void CreateGuest(const std::string& view_type,
                   content::WebContents* owner_web_contents,
                   const base::DictionaryValue& create_params,
                   WebContentsCreatedCallback callback);

  content::WebContents* CreateGuestWithWebContentsParams(
      const std::string& view_type,
      content::WebContents* owner_web_contents,
      const content::WebContents::CreateParams& create_params);

  content::SiteInstance* GetGuestSiteInstance(
      const GURL& guest_site);

  // BrowserPluginGuestManager implementation.
  content::WebContents* GetGuestByInstanceID(
      int owner_process_id,
      int element_instance_id) override;
  bool ForEachGuest(content::WebContents* owner_web_contents,
                    const GuestCallback& callback) override;
  content::WebContents* GetFullPageGuest(
      content::WebContents* embedder_web_contents) override;

 protected:
  friend class GuestViewBase;
  friend class GuestViewEvent;
  friend class GuestViewMessageFilter;

  class EmbedderRenderProcessHostObserver;

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

  virtual void AddGuest(int guest_instance_id,
                        content::WebContents* guest_web_contents);
  virtual void RemoveGuest(int guest_instance_id);

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

  // Called when a GuestView has been created in JavaScript.
  virtual void ViewCreated(int 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(int 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(int embedder_process_id,
                                    int view_instance_id);

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

  // Creates a guest of the provided |view_type|.
  GuestViewBase* CreateGuestInternal(content::WebContents* owner_web_contents,
                                     const std::string& view_type);

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

  // 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,
                     std::unique_ptr<base::DictionaryValue> args,
                     GuestViewBase* guest,
                     int instance_id);

  content::WebContents* GetGuestByInstanceID(int guest_instance_id);

  bool CanEmbedderAccessInstanceIDMaybeKill(
      int embedder_render_process_id,
      int guest_instance_id);

  bool CanEmbedderAccessInstanceID(int 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);

  static bool GetFullPageGuestHelper(content::WebContents** result,
                                     content::WebContents* guest_web_contents);

  // Contains guests' WebContents, mapping from their instance ids.
  using GuestInstanceMap = std::map<int, content::WebContents*>;
  GuestInstanceMap guest_web_contents_by_instance_id_;

  struct ElementInstanceKey {
    int embedder_process_id;
    int element_instance_id;

    ElementInstanceKey();
    ElementInstanceKey(int embedder_process_id,
                       int element_instance_id);

    bool operator<(const ElementInstanceKey& other) const;
    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_;

  using GuestViewCreateFunction =
      base::Callback<GuestViewBase*(content::WebContents*)>;
  using GuestViewCleanUpFunction =
      base::Callback<void(content::BrowserContext*, int, int)>;
  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_;

  // 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_;
  // The remaining instance IDs that are greater than
  // |last_instance_id_removed_| are kept here.
  std::set<int> removed_instance_ids_;

  content::BrowserContext* const context_;

  std::unique_ptr<GuestViewManagerDelegate> delegate_;

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

  // |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::Closure>;
  using CallbacksForEachViewID = std::map<int, Callbacks>;
  using CallbacksForEachEmbedderID = std::map<int, CallbacksForEachViewID>;
  CallbacksForEachEmbedderID view_destruction_callback_map_;

  // This is used to ensure that an EmbedderRenderProcessHostObserver will not
  // call into this GuestViewManager after it has been destroyed.
  base::WeakPtrFactory<GuestViewManager> weak_ptr_factory_;

 private:
  DISALLOW_COPY_AND_ASSIGN(GuestViewManager);
};

}  // namespace guest_view

#endif  // COMPONENTS_GUEST_VIEW_BROWSER_GUEST_VIEW_MANAGER_H_