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
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
|
// 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 EXTENSIONS_BROWSER_GUEST_VIEW_GUEST_VIEW_BASE_H_
#define EXTENSIONS_BROWSER_GUEST_VIEW_GUEST_VIEW_BASE_H_
#include <queue>
#include "base/memory/weak_ptr.h"
#include "base/values.h"
#include "components/ui/zoom/zoom_observer.h"
#include "content/public/browser/browser_plugin_guest_delegate.h"
#include "content/public/browser/guest_host.h"
#include "content/public/browser/render_process_host_observer.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "extensions/common/guest_view/guest_view_constants.h"
struct RendererContentSettingRules;
namespace extensions {
class GuestViewEvent;
// A struct of parameters for SetSize(). The parameters are all declared as
// scoped pointers since they are all optional. Null pointers indicate that the
// parameter has not been provided, and the last used value should be used. Note
// that when |enable_auto_size| is true, providing |normal_size| is not
// meaningful. This is because the normal size of the guestview is overridden
// whenever autosizing occurs.
struct SetSizeParams {
SetSizeParams();
~SetSizeParams();
scoped_ptr<bool> enable_auto_size;
scoped_ptr<gfx::Size> min_size;
scoped_ptr<gfx::Size> max_size;
scoped_ptr<gfx::Size> normal_size;
};
// A GuestViewBase is the base class browser-side API implementation for a
// <*view> tag. GuestViewBase maintains an association between a guest
// WebContents and an owner WebContents. It receives events issued from
// the guest and relays them to the owner. GuestViewBase tracks the lifetime
// of its owner. A GuestViewBase's owner is referred to as an embedder if
// it is attached to a container within the owner's WebContents.
class GuestViewBase : public content::BrowserPluginGuestDelegate,
public content::WebContentsDelegate,
public content::WebContentsObserver,
public ui_zoom::ZoomObserver {
public:
// Returns a *ViewGuest if this GuestView is of the given view type.
template <typename T>
T* As() {
if (IsViewType(T::Type))
return static_cast<T*>(this);
return nullptr;
}
static GuestViewBase* FromWebContents(
const content::WebContents* web_contents);
static GuestViewBase* From(int owner_process_id, int instance_id);
// Given a |web_contents|, returns the top level owner WebContents. If
// |web_contents| does not belong to a GuestView, it will be returned
// unchanged.
static content::WebContents* GetTopLevelWebContents(
content::WebContents* web_contents);
static bool IsGuest(content::WebContents* web_contents);
virtual const char* GetViewType() const = 0;
// This method is called after the guest has been attached to an embedder and
// suspended resource loads have been resumed.
//
// This method can be overriden by subclasses. This gives the derived class
// an opportunity to perform setup actions after attachment.
virtual void DidAttachToEmbedder() {}
// This method is called after this GuestViewBase has been initiated.
//
// This gives the derived class an opportunity to perform additional
// initialization.
virtual void DidInitialize(const base::DictionaryValue& create_params) {}
// This method is called when the initial set of frames within the page have
// completed loading.
virtual void GuestViewDidStopLoading() {}
// This method is called before the embedder is destroyed.
// |owner_web_contents_| should still be valid during this call. This
// allows the derived class to perform some cleanup related to the embedder
// web contents.
virtual void EmbedderWillBeDestroyed() {}
// This method is called when the embedder's zoom changes.
virtual void EmbedderZoomChanged(double old_zoom_level,
double new_zoom_level) {}
// This method is called when the guest WebContents has been destroyed. This
// object will be destroyed after this call returns.
//
// This gives the derived class an opportunity to perform some cleanup.
virtual void GuestDestroyed() {}
// This method is invoked when the guest RenderView is ready, e.g. because we
// recreated it after a crash or after reattachment.
//
// This gives the derived class an opportunity to perform some initialization
// work.
virtual void GuestReady() {}
// This method is called when the guest's zoom changes.
virtual void GuestZoomChanged(double old_zoom_level, double new_zoom_level) {}
// This method is called when embedder WebContents's fullscreen is toggled.
//
// If the guest asked the embedder to enter fullscreen, the guest uses this
// signal to exit fullscreen state.
virtual void EmbedderFullscreenToggled(bool entered_fullscreen) {}
// This method is invoked when the contents auto-resized to give the container
// an opportunity to match it if it wishes.
//
// This gives the derived class an opportunity to inform its container element
// or perform other actions.
virtual void GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
const gfx::Size& new_size) {}
// This method queries whether autosize is supported for this particular view.
// By default, autosize is not supported. Derived classes can override this
// behavior to support autosize.
virtual bool IsAutoSizeSupported() const;
// This method is invoked when the contents preferred size changes. This will
// only ever fire if IsPreferredSizeSupported returns true.
virtual void OnPreferredSizeChanged(const gfx::Size& pref_size) {}
// This method queries whether preferred size events are enabled for this
// view. By default, preferred size events are disabled, since they add a
// small amount of overhead.
virtual bool IsPreferredSizeModeEnabled() const;
// This method queries whether drag-and-drop is enabled for this particular
// view. By default, drag-and-drop is disabled. Derived classes can override
// this behavior to enable drag-and-drop.
virtual bool IsDragAndDropEnabled() const;
// This method is called immediately before suspended resource loads have been
// resumed on attachment to an embedder.
//
// This method can be overriden by subclasses. This gives the derived class
// an opportunity to perform setup actions before attachment.
virtual void WillAttachToEmbedder() {}
// This method is called when the guest WebContents is about to be destroyed.
//
// This gives the derived class an opportunity to perform some cleanup prior
// to destruction.
virtual void WillDestroy() {}
// This method is to be implemented by the derived class. This indicates
// whether zoom should propagate from the embedder to the guest content.
virtual bool ZoomPropagatesFromEmbedderToGuest() const;
// This method is to be implemented by the derived class. Access to guest
// views are determined by the availability of the internal extension API
// used to implement the guest view.
//
// This should be the name of the API as it appears in the _api_features.json
// file.
virtual const char* GetAPINamespace() const = 0;
// This method is to be implemented by the derived class. This method is the
// task prefix to show for a task produced by this GuestViewBase's derived
// type.
virtual int GetTaskPrefix() const = 0;
// This method is to be implemented by the derived class. Given a set of
// initialization parameters, a concrete subclass of GuestViewBase can
// create a specialized WebContents that it returns back to GuestViewBase.
using WebContentsCreatedCallback =
base::Callback<void(content::WebContents*)>;
virtual void CreateWebContents(
const base::DictionaryValue& create_params,
const WebContentsCreatedCallback& callback) = 0;
// This creates a WebContents and initializes |this| GuestViewBase to use the
// newly created WebContents.
void Init(const base::DictionaryValue& create_params,
const WebContentsCreatedCallback& callback);
void InitWithWebContents(const base::DictionaryValue& create_params,
content::WebContents* guest_web_contents);
void LoadURLWithParams(
const content::NavigationController::LoadURLParams& load_params);
bool IsViewType(const char* const view_type) const {
return !strcmp(GetViewType(), view_type);
}
// Used to toggle autosize mode for this GuestView, and set both the automatic
// and normal sizes.
void SetSize(const SetSizeParams& params);
bool initialized() const { return initialized_; }
content::WebContents* embedder_web_contents() const {
return attached() ? owner_web_contents_ : nullptr;
}
content::WebContents* owner_web_contents() const {
return owner_web_contents_;
}
content::GuestHost* host() const {
return guest_host_;
}
// Returns the parameters associated with the element hosting this GuestView
// passed in from JavaScript.
base::DictionaryValue* attach_params() const { return attach_params_.get(); }
// Returns whether this guest has an associated embedder.
bool attached() const {
return element_instance_id_ != guestview::kInstanceIDNone;
}
// Returns the instance ID of the <*view> element.
int view_instance_id() const { return view_instance_id_; }
// Returns the instance ID of this GuestViewBase.
int guest_instance_id() const { return guest_instance_id_; }
// Returns the instance ID of the GuestViewBase's element.
int element_instance_id() const { return element_instance_id_; }
// Returns the extension ID of the embedder.
const std::string& owner_extension_id() const {
return owner_extension_id_;
}
// Returns whether this GuestView is embedded in an extension/app.
bool in_extension() const { return !owner_extension_id_.empty(); }
bool can_owner_receive_events() const { return !!view_instance_id_; }
// Returns the user browser context of the embedder.
content::BrowserContext* browser_context() const { return browser_context_; }
GuestViewBase* GetOpener() const {
return opener_.get();
}
// Returns the URL of the owner WebContents.
const GURL& GetOwnerSiteURL() const;
// Whether the guest view is inside a plugin document.
bool is_full_page_plugin() const { return is_full_page_plugin_; }
// Returns the routing ID of the guest proxy in the owner's renderer process.
// This value is only valid after attachment or first navigation.
int proxy_routing_id() const { return guest_proxy_routing_id_; }
// Destroy this guest.
void Destroy();
// Saves the attach state of the custom element hosting this GuestView.
void SetAttachParams(const base::DictionaryValue& params);
void SetOpener(GuestViewBase* opener);
// BrowserPluginGuestDelegate implementation.
content::WebContents* CreateNewGuestWindow(
const content::WebContents::CreateParams& create_params) final;
void DidAttach(int guest_proxy_routing_id) final;
void DidDetach() final;
content::WebContents* GetOwnerWebContents() const final;
void GuestSizeChanged(const gfx::Size& new_size) final;
void SetGuestHost(content::GuestHost* guest_host) final;
void WillAttach(content::WebContents* embedder_web_contents,
int browser_plugin_instance_id,
bool is_full_page_plugin) final;
// ui_zoom::ZoomObserver implementation.
void OnZoomChanged(
const ui_zoom::ZoomController::ZoomChangedEventData& data) final;
// Dispatches an event to the guest proxy.
void DispatchEventToGuestProxy(GuestViewEvent* event);
// Dispatches an event to the view.
void DispatchEventToView(GuestViewEvent* event);
protected:
explicit GuestViewBase(content::WebContents* owner_web_contents);
~GuestViewBase() override;
// Convert sizes in pixels from logical to physical numbers of pixels.
// Note that a size can consist of a fractional number of logical pixels
// (hence |logical_pixels| is represented as a double), but will always
// consist of an integral number of physical pixels (hence the return value
// is represented as an int).
int LogicalPixelsToPhysicalPixels(double logical_pixels) const;
// Convert sizes in pixels from physical to logical numbers of pixels.
// Note that a size can consist of a fractional number of logical pixels
// (hence the return value is represented as a double), but will always
// consist of an integral number of physical pixels (hence |physical_pixels|
// is represented as an int).
double PhysicalPixelsToLogicalPixels(int physical_pixels) const;
// WebContentsObserver implementation.
void DidStopLoading() final;
void RenderViewReady() final;
void WebContentsDestroyed() final;
void DidNavigateMainFrame(
const content::LoadCommittedDetails& details,
const content::FrameNavigateParams& params) override;
// WebContentsDelegate implementation.
void ActivateContents(content::WebContents* contents) final;
void DeactivateContents(content::WebContents* contents) final;
void ContentsMouseEvent(content::WebContents* source,
const gfx::Point& location,
bool motion) override;
void ContentsZoomChange(bool zoom_in) override;
void HandleKeyboardEvent(
content::WebContents* source,
const content::NativeWebKeyboardEvent& event) override;
void LoadingStateChanged(content::WebContents* source,
bool to_different_document) final;
content::ColorChooser* OpenColorChooser(
content::WebContents* web_contents,
SkColor color,
const std::vector<content::ColorSuggestion>& suggestions) override;
void RunFileChooser(content::WebContents* web_contents,
const content::FileChooserParams& params) override;
bool ShouldFocusPageAfterCrash() final;
bool PreHandleGestureEvent(content::WebContents* source,
const blink::WebGestureEvent& event) override;
void UpdatePreferredSize(content::WebContents* web_contents,
const gfx::Size& pref_size) final;
void UpdateTargetURL(content::WebContents* source, const GURL& url) override;
void SetGuestZoomLevelToMatchEmbedder();
private:
class OwnerContentsObserver;
class OpenerLifetimeObserver;
void SendQueuedEvents();
void CompleteInit(scoped_ptr<base::DictionaryValue> create_params,
const WebContentsCreatedCallback& callback,
content::WebContents* guest_web_contents);
// Dispatches the onResize event to the embedder.
void DispatchOnResizeEvent(const gfx::Size& old_size,
const gfx::Size& new_size);
// Returns the default size of the guestview.
gfx::Size GetDefaultSize() const;
// Get the zoom factor for the embedder's web contents.
double GetEmbedderZoomFactor() const;
void SetUpSizing(const base::DictionaryValue& params);
void StartTrackingEmbedderZoomLevel();
void StopTrackingEmbedderZoomLevel();
// This guest tracks the lifetime of the WebContents specified by
// |owner_web_contents_|. If |owner_web_contents_| is destroyed then this
// guest will also self-destruct.
content::WebContents* owner_web_contents_;
std::string owner_extension_id_;
content::BrowserContext* const browser_context_;
// |guest_instance_id_| is a profile-wide unique identifier for a guest
// WebContents.
const int guest_instance_id_;
// |view_instance_id_| is an identifier that's unique within a particular
// embedder RenderViewHost for a particular <*view> instance.
int view_instance_id_;
// |element_instance_id_| is an identifer that's unique to a particular
// GuestViewContainer element.
int element_instance_id_;
// |initialized_| indicates whether GuestViewBase::Init has been called for
// this object.
bool initialized_;
// Indicates that this guest is in the process of being destroyed.
bool is_being_destroyed_;
// This is a queue of Events that are destined to be sent to the embedder once
// the guest is attached to a particular embedder.
std::deque<linked_ptr<GuestViewEvent> > pending_events_;
// The opener guest view.
base::WeakPtr<GuestViewBase> opener_;
// The parameters associated with the element hosting this GuestView that
// are passed in from JavaScript. This will typically be the view instance ID,
// and element-specific parameters. These parameters are passed along to new
// guests that are created from this guest.
scoped_ptr<base::DictionaryValue> attach_params_;
// This observer ensures that this guest self-destructs if the embedder goes
// away.
scoped_ptr<OwnerContentsObserver> owner_contents_observer_;
// This observer ensures that if the guest is unattached and its opener goes
// away then this guest also self-destructs.
scoped_ptr<OpenerLifetimeObserver> opener_lifetime_observer_;
// The size of the guest content. Note: In autosize mode, the container
// element may not match the size of the guest.
gfx::Size guest_size_;
// A pointer to the guest_host.
content::GuestHost* guest_host_;
// Indicates whether autosize mode is enabled or not.
bool auto_size_enabled_;
// The maximum size constraints of the container element in autosize mode.
gfx::Size max_auto_size_;
// The minimum size constraints of the container element in autosize mode.
gfx::Size min_auto_size_;
// The size that will be used when autosize mode is disabled.
gfx::Size normal_size_;
// Whether the guest view is inside a plugin document.
bool is_full_page_plugin_;
// The routing ID of the proxy to the guest in the owner's renderer process.
int guest_proxy_routing_id_;
// This is used to ensure pending tasks will not fire after this object is
// destroyed.
base::WeakPtrFactory<GuestViewBase> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(GuestViewBase);
};
} // namespace extensions
#endif // EXTENSIONS_BROWSER_GUEST_VIEW_GUEST_VIEW_BASE_H_
|