1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef EXTENSIONS_BROWSER_GUEST_VIEW_GUEST_VIEW_BASE_H_
6#define EXTENSIONS_BROWSER_GUEST_VIEW_GUEST_VIEW_BASE_H_
7
8#include <queue>
9
10#include "base/memory/weak_ptr.h"
11#include "base/values.h"
12#include "content/public/browser/browser_plugin_guest_delegate.h"
13#include "content/public/browser/render_process_host_observer.h"
14#include "content/public/browser/web_contents.h"
15#include "content/public/browser/web_contents_delegate.h"
16#include "content/public/browser/web_contents_observer.h"
17
18struct RendererContentSettingRules;
19
20namespace extensions {
21
22// A GuestViewBase is the base class browser-side API implementation for a
23// <*view> tag. GuestViewBase maintains an association between a guest
24// WebContents and an embedder WebContents. It receives events issued from
25// the guest and relays them to the embedder. GuestViewBase tracks the lifetime
26// of its embedder render process until it is attached to a particular embedder
27// WebContents. At that point, its lifetime is restricted in scope to the
28// lifetime of its embedder WebContents.
29class GuestViewBase : public content::BrowserPluginGuestDelegate,
30                      public content::RenderProcessHostObserver,
31                      public content::WebContentsDelegate,
32                      public content::WebContentsObserver {
33 public:
34  class Event {
35   public:
36    Event(const std::string& name, scoped_ptr<base::DictionaryValue> args);
37    ~Event();
38
39    const std::string& name() const { return name_; }
40
41    scoped_ptr<base::DictionaryValue> GetArguments();
42
43   private:
44    const std::string name_;
45    scoped_ptr<base::DictionaryValue> args_;
46  };
47
48  // Returns a *ViewGuest if this GuestView is of the given view type.
49  template <typename T>
50  T* As() {
51    if (IsViewType(T::Type))
52      return static_cast<T*>(this);
53
54    return NULL;
55  }
56
57  typedef base::Callback<GuestViewBase*(
58      content::BrowserContext*, int)> GuestCreationCallback;
59  static void RegisterGuestViewType(const std::string& view_type,
60                                    const GuestCreationCallback& callback);
61
62  static GuestViewBase* Create(content::BrowserContext* browser_context,
63                               int guest_instance_id,
64                               const std::string& view_type);
65
66  static GuestViewBase* FromWebContents(content::WebContents* web_contents);
67
68  static GuestViewBase* From(int embedder_process_id, int instance_id);
69
70  static bool IsGuest(content::WebContents* web_contents);
71
72  virtual const char* GetViewType() const = 0;
73
74  // This method is called after the guest has been attached to an embedder and
75  // suspended resource loads have been resumed.
76  //
77  // This method can be overriden by subclasses. This gives the derived class
78  // an opportunity to perform setup actions after attachment.
79  virtual void DidAttachToEmbedder() {}
80
81  // This method is called after this GuestViewBase has been initiated.
82  //
83  // This gives the derived class an opportunity to perform additional
84  // initialization.
85  virtual void DidInitialize() {}
86
87  // This method is called when the initial set of frames within the page have
88  // completed loading.
89  virtual void DidStopLoading() {}
90
91  // This method is called when the guest's embedder WebContents has been
92  // destroyed and the guest will be destroyed shortly.
93  //
94  // This gives the derived class an opportunity to perform some cleanup prior
95  // to destruction.
96  virtual void EmbedderDestroyed() {}
97
98  // This method is called when the guest WebContents has been destroyed. This
99  // object will be destroyed after this call returns.
100  //
101  // This gives the derived class an opportunity to perform some cleanup.
102  virtual void GuestDestroyed() {}
103
104  // This method is invoked when the guest RenderView is ready, e.g. because we
105  // recreated it after a crash.
106  //
107  // This gives the derived class an opportunity to perform some initialization
108  // work.
109  virtual void GuestReady() {}
110
111  // This method is invoked when the contents auto-resized to give the container
112  // an opportunity to match it if it wishes.
113  //
114  // This gives the derived class an opportunity to inform its container element
115  // or perform other actions.
116  virtual void GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
117                                             const gfx::Size& new_size) {}
118
119  // This method queries whether autosize is supported for this particular view.
120  // By default, autosize is not supported. Derived classes can override this
121  // behavior to support autosize.
122  virtual bool IsAutoSizeSupported() const;
123
124  // This method queries whether drag-and-drop is enabled for this particular
125  // view. By default, drag-and-drop is disabled. Derived classes can override
126  // this behavior to enable drag-and-drop.
127  virtual bool IsDragAndDropEnabled() const;
128
129  // This method is called immediately before suspended resource loads have been
130  // resumed on attachment to an embedder.
131  //
132  // This method can be overriden by subclasses. This gives the derived class
133  // an opportunity to perform setup actions before attachment.
134  virtual void WillAttachToEmbedder() {}
135
136  // This method is called when the guest WebContents is about to be destroyed.
137  //
138  // This gives the derived class an opportunity to perform some cleanup prior
139  // to destruction.
140  virtual void WillDestroy() {}
141
142  // This method is to be implemented by the derived class. Access to guest
143  // views are determined by the availability of the internal extension API
144  // used to implement the guest view.
145  //
146  // This should be the name of the API as it appears in the _api_features.json
147  // file.
148  virtual const char* GetAPINamespace() const = 0;
149
150  // This method is to be implemented by the derived class. This method is the
151  // task prefix to show for a task produced by this GuestViewBase's derived
152  // type.
153  virtual int GetTaskPrefix() const = 0;
154
155  // This method is to be implemented by the derived class. Given a set of
156  // initialization parameters, a concrete subclass of GuestViewBase can
157  // create a specialized WebContents that it returns back to GuestViewBase.
158  typedef base::Callback<void(content::WebContents*)>
159      WebContentsCreatedCallback;
160  virtual void CreateWebContents(
161      const std::string& embedder_extension_id,
162      int embedder_render_process_id,
163      const GURL& embedder_site_url,
164      const base::DictionaryValue& create_params,
165      const WebContentsCreatedCallback& callback) = 0;
166
167  // This creates a WebContents and initializes |this| GuestViewBase to use the
168  // newly created WebContents.
169  void Init(const std::string& embedder_extension_id,
170            content::WebContents* embedder_web_contents,
171            const base::DictionaryValue& create_params,
172            const WebContentsCreatedCallback& callback);
173
174  void InitWithWebContents(
175      const std::string& embedder_extension_id,
176      int embedder_render_process_id,
177      content::WebContents* guest_web_contents);
178
179  bool IsViewType(const char* const view_type) const {
180    return !strcmp(GetViewType(), view_type);
181  }
182
183  // Toggles autosize mode for this GuestView.
184  void SetAutoSize(bool enabled,
185                   const gfx::Size& min_size,
186                   const gfx::Size& max_size);
187
188  base::WeakPtr<GuestViewBase> AsWeakPtr();
189
190  bool initialized() const { return initialized_; }
191
192  content::WebContents* embedder_web_contents() const {
193    return embedder_web_contents_;
194  }
195
196  // Returns the parameters associated with the element hosting this GuestView
197  // passed in from JavaScript.
198  base::DictionaryValue* attach_params() const { return attach_params_.get(); }
199
200  // Returns whether this guest has an associated embedder.
201  bool attached() const { return !!embedder_web_contents_; }
202
203  // Returns the instance ID of the <*view> element.
204  int view_instance_id() const { return view_instance_id_; }
205
206  // Returns the instance ID of this GuestViewBase.
207  int guest_instance_id() const { return guest_instance_id_; }
208
209  // Returns the extension ID of the embedder.
210  const std::string& embedder_extension_id() const {
211    return embedder_extension_id_;
212  }
213
214  // Returns whether this GuestView is embedded in an extension/app.
215  bool in_extension() const { return !embedder_extension_id_.empty(); }
216
217  // Returns the user browser context of the embedder.
218  content::BrowserContext* browser_context() const { return browser_context_; }
219
220  // Returns the embedder's process ID.
221  int embedder_render_process_id() const { return embedder_render_process_id_; }
222
223  GuestViewBase* GetOpener() const {
224    return opener_.get();
225  }
226
227  // Sets some additional chrome/ initialization parameters.
228  void SetAttachParams(const base::DictionaryValue& params);
229  void SetOpener(GuestViewBase* opener);
230
231  // RenderProcessHostObserver implementation
232  virtual void RenderProcessExited(content::RenderProcessHost* host,
233                                   base::ProcessHandle handle,
234                                   base::TerminationStatus status,
235                                   int exit_code) OVERRIDE;
236
237  // BrowserPluginGuestDelegate implementation.
238  virtual void Destroy() OVERRIDE FINAL;
239  virtual void DidAttach(int guest_proxy_routing_id) OVERRIDE FINAL;
240  virtual void ElementSizeChanged(const gfx::Size& old_size,
241                                  const gfx::Size& new_size) OVERRIDE FINAL;
242  virtual void GuestSizeChanged(const gfx::Size& old_size,
243                                const gfx::Size& new_size) OVERRIDE FINAL;
244  virtual void RegisterDestructionCallback(
245      const DestructionCallback& callback) OVERRIDE FINAL;
246  virtual void WillAttach(
247      content::WebContents* embedder_web_contents,
248      int browser_plugin_instance_id) OVERRIDE FINAL;
249
250  // Dispatches an event |event_name| to the embedder with the |event| fields.
251  void DispatchEventToEmbedder(Event* event);
252
253 protected:
254  GuestViewBase(content::BrowserContext* browser_context,
255                int guest_instance_id);
256
257  virtual ~GuestViewBase();
258
259 private:
260  class EmbedderWebContentsObserver;
261
262  void SendQueuedEvents();
263
264  void CompleteInit(const std::string& embedder_extension_id,
265                    int embedder_render_process_id,
266                    const WebContentsCreatedCallback& callback,
267                    content::WebContents* guest_web_contents);
268
269  static void RegisterGuestViewTypes();
270
271  // WebContentsObserver implementation.
272  virtual void DidStopLoading(
273      content::RenderViewHost* render_view_host) OVERRIDE FINAL;
274  virtual void RenderViewReady() OVERRIDE FINAL;
275  virtual void WebContentsDestroyed() OVERRIDE FINAL;
276
277  // WebContentsDelegate implementation.
278  virtual void ActivateContents(content::WebContents* contents) OVERRIDE FINAL;
279  virtual void DeactivateContents(
280      content::WebContents* contents) OVERRIDE FINAL;
281  virtual void RunFileChooser(
282      content::WebContents* web_contents,
283      const content::FileChooserParams& params) OVERRIDE;
284  virtual bool ShouldFocusPageAfterCrash() OVERRIDE FINAL;
285  virtual bool PreHandleGestureEvent(
286      content::WebContents* source,
287      const blink::WebGestureEvent& event) OVERRIDE FINAL;
288
289  content::WebContents* embedder_web_contents_;
290  std::string embedder_extension_id_;
291  int embedder_render_process_id_;
292  content::BrowserContext* browser_context_;
293
294  // |guest_instance_id_| is a profile-wide unique identifier for a guest
295  // WebContents.
296  const int guest_instance_id_;
297
298  // |view_instance_id_| is an identifier that's unique within a particular
299  // embedder RenderViewHost for a particular <*view> instance.
300  int view_instance_id_;
301
302  // |element_instance_id_| is an identififer that's unique to a particular
303  // GuestViewContainer element.
304  int element_instance_id_;
305
306  bool initialized_;
307
308  // This is a queue of Events that are destined to be sent to the embedder once
309  // the guest is attached to a particular embedder.
310  std::deque<linked_ptr<Event> > pending_events_;
311
312  // The opener guest view.
313  base::WeakPtr<GuestViewBase> opener_;
314
315  DestructionCallback destruction_callback_;
316
317  // The parameters associated with the element hosting this GuestView that
318  // are passed in from JavaScript. This will typically be the view instance ID,
319  // and element-specific parameters. These parameters are passed along to new
320  // guests that are created from this guest.
321  scoped_ptr<base::DictionaryValue> attach_params_;
322
323  scoped_ptr<EmbedderWebContentsObserver> embedder_web_contents_observer_;
324
325  // The size of the container element.
326  gfx::Size element_size_;
327
328  // The size of the guest content. Note: In autosize mode, the container
329  // element may not match the size of the guest.
330  gfx::Size guest_size_;
331
332  // Indicates whether autosize mode is enabled or not.
333  bool auto_size_enabled_;
334
335  // The maximum size constraints of the container element in autosize mode.
336  gfx::Size max_auto_size_;
337
338  // The minimum size constraints of the container element in autosize mode.
339  gfx::Size min_auto_size_;
340
341  // This is used to ensure pending tasks will not fire after this object is
342  // destroyed.
343  base::WeakPtrFactory<GuestViewBase> weak_ptr_factory_;
344
345  DISALLOW_COPY_AND_ASSIGN(GuestViewBase);
346};
347
348}  // namespace extensions
349
350#endif  // EXTENSIONS_BROWSER_GUEST_VIEW_GUEST_VIEW_BASE_H_
351