1 // Copyright (c) 2012 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.
5 // A BrowserPluginGuest is the browser side of a browser <--> embedder
6 // renderer channel. A BrowserPlugin (a WebPlugin) is on the embedder
7 // renderer side of browser <--> embedder renderer communication.
9 // BrowserPluginGuest lives on the UI thread of the browser process. Any
10 // messages about the guest render process that the embedder might be interested
11 // in receiving should be listened for here.
13 // BrowserPluginGuest is a WebContentsObserver for the guest WebContents.
14 // BrowserPluginGuest operates under the assumption that the guest will be
15 // accessible through only one RenderViewHost for the lifetime of
16 // the guest WebContents. Thus, cross-process navigation is not supported.
18 #ifndef CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_H_
19 #define CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_H_
24 #include "base/compiler_specific.h"
25 #include "base/memory/linked_ptr.h"
26 #include "base/memory/weak_ptr.h"
27 #include "base/values.h"
28 #include "content/common/edit_command.h"
29 #include "content/common/input/input_event_ack_state.h"
30 #include "content/public/browser/browser_plugin_guest_delegate.h"
31 #include "content/public/browser/guest_host.h"
32 #include "content/public/browser/readback_types.h"
33 #include "content/public/browser/web_contents_observer.h"
34 #include "third_party/WebKit/public/platform/WebFocusType.h"
35 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
36 #include "third_party/WebKit/public/web/WebDragOperation.h"
37 #include "third_party/WebKit/public/web/WebDragStatus.h"
38 #include "third_party/WebKit/public/web/WebInputEvent.h"
39 #include "ui/base/ime/text_input_mode.h"
40 #include "ui/base/ime/text_input_type.h"
41 #include "ui/gfx/geometry/rect.h"
43 struct BrowserPluginHostMsg_Attach_Params
;
44 struct FrameHostMsg_CompositorFrameSwappedACK_Params
;
45 struct FrameHostMsg_ReclaimCompositorResources_Params
;
46 struct FrameMsg_CompositorFrameSwapped_Params
;
47 struct ViewHostMsg_TextInputState_Params
;
49 #if defined(OS_MACOSX)
50 struct FrameHostMsg_ShowPopup_Params
;
54 class CompositorFrame
;
56 struct SurfaceSequence
;
65 class BrowserPluginGuestManager
;
66 class RenderViewHostImpl
;
67 class RenderWidgetHost
;
68 class RenderWidgetHostView
;
69 class RenderWidgetHostViewBase
;
73 // A browser plugin guest provides functionality for WebContents to operate in
74 // the guest role and implements guest-specific overrides for ViewHostMsg_*
77 // When a guest is initially created, it is in an unattached state. That is,
78 // it is not visible anywhere and has no embedder WebContents assigned.
79 // A BrowserPluginGuest is said to be "attached" if it has an embedder.
80 // A BrowserPluginGuest can also create a new unattached guest via
81 // CreateNewWindow. The newly created guest will live in the same partition,
82 // which means it can share storage and can script this guest.
84 // Note: in --site-per-process, all IPCs sent out from this class will be
85 // dropped on the floor since we don't have a BrowserPlugin.
86 class CONTENT_EXPORT BrowserPluginGuest
: public GuestHost
,
87 public WebContentsObserver
{
89 ~BrowserPluginGuest() override
;
91 // The WebContents passed into the factory method here has not been
92 // initialized yet and so it does not yet hold a SiteInstance.
93 // BrowserPluginGuest must be constructed and installed into a WebContents
94 // prior to its initialization because WebContents needs to determine what
95 // type of WebContentsView to construct on initialization. The content
96 // embedder needs to be aware of |guest_site_instance| on the guest's
97 // construction and so we pass it in here.
98 static BrowserPluginGuest
* Create(WebContentsImpl
* web_contents
,
99 BrowserPluginGuestDelegate
* delegate
);
101 // Returns whether the given WebContents is a BrowserPlugin guest.
102 static bool IsGuest(WebContentsImpl
* web_contents
);
104 // Returns whether the given RenderviewHost is a BrowserPlugin guest.
105 static bool IsGuest(RenderViewHostImpl
* render_view_host
);
107 // BrowserPluginGuest::Init is called after the associated guest WebContents
108 // initializes. If this guest cannot navigate without being attached to a
109 // container, then this call is a no-op. For guest types that can be
110 // navigated, this call adds the associated RenderWdigetHostViewGuest to the
111 // view hierachy and sets up the appropriate RendererPreferences so that this
112 // guest can navigate and resize offscreen.
115 // Returns a WeakPtr to this BrowserPluginGuest.
116 base::WeakPtr
<BrowserPluginGuest
> AsWeakPtr();
118 // Sets the focus state of the current RenderWidgetHostView.
119 void SetFocus(RenderWidgetHost
* rwh
,
121 blink::WebFocusType focus_type
);
123 // Sets the tooltip text.
124 void SetTooltipText(const base::string16
& tooltip_text
);
126 // Sets the lock state of the pointer. Returns true if |allowed| is true and
127 // the mouse has been successfully locked.
128 bool LockMouse(bool allowed
);
130 // Return true if the mouse is locked.
131 bool mouse_locked() const { return mouse_locked_
; }
133 // Called when the embedder WebContents changes visibility.
134 void EmbedderVisibilityChanged(bool visible
);
136 // Creates a new guest WebContentsImpl with the provided |params| with |this|
138 WebContentsImpl
* CreateNewGuestWindow(
139 const WebContents::CreateParams
& params
);
141 // Creates, if necessary, and returns the routing ID of a proxy for the guest
142 // in the owner's renderer process.
143 int GetGuestProxyRoutingID();
145 // Returns the identifier that uniquely identifies a browser plugin guest
146 // within an embedder.
147 int browser_plugin_instance_id() const { return browser_plugin_instance_id_
; }
149 bool OnMessageReceivedFromEmbedder(const IPC::Message
& message
);
151 WebContentsImpl
* embedder_web_contents() const {
152 return attached_
? owner_web_contents_
: nullptr;
155 // Returns the embedder's RenderWidgetHostView if it is available.
156 // Returns nullptr otherwise.
157 RenderWidgetHostView
* GetOwnerRenderWidgetHostView();
159 bool focused() const { return focused_
; }
160 bool visible() const { return guest_visible_
; }
161 bool is_in_destruction() { return is_in_destruction_
; }
163 void UpdateVisibility();
165 BrowserPluginGuestManager
* GetBrowserPluginGuestManager() const;
167 // WebContentsObserver implementation.
168 void DidCommitProvisionalLoadForFrame(
169 RenderFrameHost
* render_frame_host
,
171 ui::PageTransition transition_type
) override
;
173 void RenderViewReady() override
;
174 void RenderProcessGone(base::TerminationStatus status
) override
;
175 bool OnMessageReceived(const IPC::Message
& message
) override
;
176 bool OnMessageReceived(const IPC::Message
& message
,
177 RenderFrameHost
* render_frame_host
) override
;
179 // GuestHost implementation.
180 int LoadURLWithParams(
181 const NavigationController::LoadURLParams
& load_params
) override
;
182 void SizeContents(const gfx::Size
& new_size
) override
;
183 void WillDestroy() override
;
185 // Exposes the protected web_contents() from WebContentsObserver.
186 WebContentsImpl
* GetWebContents() const;
188 gfx::Point
GetScreenCoordinates(const gfx::Point
& relative_position
) const;
190 // This method is called by the RenderWidgetHostViewGuest to inform the
191 // BrowserPlugin of the potential location of the context menu event (to
192 // come). The need for this (hack) is that the input events when passed on to
193 // the BrowserPlugin are modified by any CSS transforms applied on the plugin.
194 // Therefore, the coordinates of the context menu event with respect to the
195 // container window are modifed with the guest renderer process beiung unaware
196 // of the change. Then eventually, when the context menu event arrives at the
197 // browser, it contains the wrong coordinates (BUG=470087).
198 // TODO(ekaramad): Find a more fundamental solution and remove this later.
199 void SetContextMenuPosition(const gfx::Point
& position
);
201 // Helper to send messages to embedder. If this guest is not yet attached,
202 // then IPCs will be queued until attachment.
203 void SendMessageToEmbedder(IPC::Message
* msg
);
205 // Returns whether the guest is attached to an embedder.
206 bool attached() const { return attached_
; }
208 // Returns true when an attachment has taken place since the last time the
209 // compositor surface was set.
210 bool has_attached_since_surface_set() const {
211 return has_attached_since_surface_set_
;
214 // Attaches this BrowserPluginGuest to the provided |embedder_web_contents|
215 // and initializes the guest with the provided |params|. Attaching a guest
216 // to an embedder implies that this guest's lifetime is no longer managed
217 // by its opener, and it can begin loading resources.
218 void Attach(int browser_plugin_instance_id
,
219 WebContentsImpl
* embedder_web_contents
,
220 const BrowserPluginHostMsg_Attach_Params
& params
);
222 // Returns whether BrowserPluginGuest is interested in receiving the given
224 static bool ShouldForwardToBrowserPluginGuest(const IPC::Message
& message
);
226 void DragSourceEndedAt(int client_x
, int client_y
, int screen_x
,
227 int screen_y
, blink::WebDragOperation operation
);
229 // Called when the drag started by this guest ends at an OS-level.
230 void EmbedderSystemDragEnded();
231 void EndSystemDragIfApplicable();
233 void RespondToPermissionRequest(int request_id
,
235 const std::string
& user_input
);
237 void PointerLockPermissionResponse(bool allow
);
239 // The next three functions are virtual for test purposes.
240 virtual void UpdateGuestSizeIfNecessary(const gfx::Size
& frame_size
,
242 virtual void SwapCompositorFrame(uint32 output_surface_id
,
245 scoped_ptr
<cc::CompositorFrame
> frame
);
246 virtual void SetChildFrameSurface(const cc::SurfaceId
& surface_id
,
247 const gfx::Size
& frame_size
,
249 const cc::SurfaceSequence
& sequence
);
251 void SetContentsOpaque(bool opaque
);
253 // Find the given |search_text| in the page. Returns true if the find request
254 // is handled by this browser plugin guest.
255 bool Find(int request_id
,
256 const base::string16
& search_text
,
257 const blink::WebFindOptions
& options
);
258 bool StopFinding(StopFindAction action
);
262 // BrowserPluginGuest is a WebContentsObserver of |web_contents| and
263 // |web_contents| has to stay valid for the lifetime of BrowserPluginGuest.
264 // Constructor protected for testing.
265 BrowserPluginGuest(bool has_render_view
,
266 WebContentsImpl
* web_contents
,
267 BrowserPluginGuestDelegate
* delegate
);
269 // Protected for testing.
270 void set_has_attached_since_surface_set_for_test(bool has_attached
) {
271 has_attached_since_surface_set_
= has_attached
;
274 void set_attached_for_test(bool attached
) {
275 attached_
= attached
;
279 class EmbedderVisibilityObserver
;
281 void InitInternal(const BrowserPluginHostMsg_Attach_Params
& params
,
282 WebContentsImpl
* owner_web_contents
);
284 void OnSatisfySequence(int instance_id
, const cc::SurfaceSequence
& sequence
);
285 void OnRequireSequence(int instance_id
,
286 const cc::SurfaceId
& id
,
287 const cc::SurfaceSequence
& sequence
);
288 // Message handlers for messages from embedder.
289 void OnCompositorFrameSwappedACK(
291 const FrameHostMsg_CompositorFrameSwappedACK_Params
& params
);
292 void OnDetach(int instance_id
);
293 // Handles drag events from the embedder.
294 // When dragging, the drag events go to the embedder first, and if the drag
295 // happens on the browser plugin, then the plugin sends a corresponding
296 // drag-message to the guest. This routes the drag-message to the guest
298 void OnDragStatusUpdate(int instance_id
,
299 blink::WebDragStatus drag_status
,
300 const DropData
& drop_data
,
301 blink::WebDragOperationsMask drag_mask
,
302 const gfx::Point
& location
);
303 // Instructs the guest to execute an edit command decoded in the embedder.
304 void OnExecuteEditCommand(int instance_id
,
305 const std::string
& command
);
307 // Returns compositor resources reclaimed in the embedder to the guest.
308 void OnReclaimCompositorResources(
310 const FrameHostMsg_ReclaimCompositorResources_Params
& params
);
312 void OnLockMouse(bool user_gesture
,
313 bool last_unlocked_by_target
,
315 void OnLockMouseAck(int instance_id
, bool succeeded
);
316 // Resizes the guest's web contents.
317 void OnSetFocus(int instance_id
,
319 blink::WebFocusType focus_type
);
320 // Sets the name of the guest so that other guests in the same partition can
322 void OnSetName(int instance_id
, const std::string
& name
);
323 // Updates the size state of the guest.
324 void OnSetEditCommandsForNextKeyEvent(
326 const std::vector
<EditCommand
>& edit_commands
);
327 // The guest WebContents is visible if both its embedder is visible and
328 // the browser plugin element is visible. If either one is not then the
329 // WebContents is marked as hidden. A hidden WebContents will consume
330 // fewer GPU and CPU resources.
332 // When every WebContents in a RenderProcessHost is hidden, it will lower
333 // the priority of the process (see RenderProcessHostImpl::WidgetHidden).
335 // It will also send a message to the guest renderer process to cleanup
336 // resources such as dropping back buffers and adjusting memory limits (if in
337 // compositing mode, see CCLayerTreeHost::setVisible).
339 // Additionally, it will slow down Javascript execution and garbage
340 // collection. See RenderThreadImpl::IdleHandler (executed when hidden) and
341 // RenderThreadImpl::IdleHandlerInForegroundTab (executed when visible).
342 void OnSetVisibility(int instance_id
, bool visible
);
343 void OnUnlockMouse();
344 void OnUnlockMouseAck(int instance_id
);
345 void OnUpdateGeometry(int instance_id
, const gfx::Rect
& view_rect
);
347 void OnTextInputStateChanged(
348 const ViewHostMsg_TextInputState_Params
& params
);
349 void OnImeSetComposition(
351 const std::string
& text
,
352 const std::vector
<blink::WebCompositionUnderline
>& underlines
,
355 void OnImeConfirmComposition(
357 const std::string
& text
,
358 bool keep_selection
);
359 void OnExtendSelectionAndDelete(int instance_id
, int before
, int after
);
360 void OnImeCancelComposition();
361 #if defined(OS_MACOSX) || defined(USE_AURA)
362 void OnImeCompositionRangeChanged(
363 const gfx::Range
& range
,
364 const std::vector
<gfx::Rect
>& character_bounds
);
367 // Message handlers for messages from guest.
368 void OnHandleInputEventAck(
369 blink::WebInputEvent::Type event_type
,
370 InputEventAckState ack_result
);
371 void OnHasTouchEventHandlers(bool accept
);
372 #if defined(OS_MACOSX)
373 // On MacOS X popups are painted by the browser process. We handle them here
374 // so that they are positioned correctly.
375 void OnShowPopup(RenderFrameHost
* render_frame_host
,
376 const FrameHostMsg_ShowPopup_Params
& params
);
378 void OnShowWidget(int route_id
, const gfx::Rect
& initial_rect
);
379 void OnTakeFocus(bool reverse
);
380 void OnUpdateFrameName(int frame_id
,
382 const std::string
& name
);
384 // Called when WillAttach is complete.
385 void OnWillAttachComplete(WebContentsImpl
* embedder_web_contents
,
386 const BrowserPluginHostMsg_Attach_Params
& params
);
388 // Forwards all messages from the |pending_messages_| queue to the embedder.
389 void SendQueuedMessages();
391 void SendTextInputTypeChangedToView(RenderWidgetHostViewBase
* guest_rwhv
);
393 // The last tooltip that was set with SetTooltipText().
394 base::string16 current_tooltip_text_
;
396 scoped_ptr
<EmbedderVisibilityObserver
> embedder_visibility_observer_
;
397 WebContentsImpl
* owner_web_contents_
;
399 // Indicates whether this guest has been attached to a container.
402 // Used to signal if a browser plugin has been attached since the last time
403 // the compositing surface was set.
404 bool has_attached_since_surface_set_
;
406 // An identifier that uniquely identifies a browser plugin within an embedder.
407 int browser_plugin_instance_id_
;
408 gfx::Rect guest_window_rect_
;
411 bool pending_lock_request_
;
413 bool embedder_visible_
;
414 // Whether the browser plugin is inside a plugin document.
415 bool is_full_page_plugin_
;
417 // Indicates that this BrowserPluginGuest has associated renderer-side state.
418 // This is used to determine whether or not to create a new RenderView when
419 // this guest is attached. A BrowserPluginGuest would have renderer-side state
420 // prior to attachment if it is created via a call to window.open and
421 // maintains a JavaScript reference to its opener.
422 bool has_render_view_
;
424 // Last seen size of guest contents (by SwapCompositorFrame).
425 gfx::Size last_seen_view_size_
;
427 bool is_in_destruction_
;
429 // BrowserPluginGuest::Init can only be called once. This flag allows it to
430 // exit early if it's already been called.
433 // Text input type states.
434 ui::TextInputType last_text_input_type_
;
435 ui::TextInputMode last_input_mode_
;
436 int last_input_flags_
;
437 bool last_can_compose_inline_
;
439 // The is the routing ID for a swapped out RenderView for the guest
440 // WebContents in the embedder's process.
441 int guest_proxy_routing_id_
;
442 // Last seen state of drag status update.
443 blink::WebDragStatus last_drag_status_
;
444 // Whether or not our embedder has seen a SystemDragEnded() call.
445 bool seen_embedder_system_drag_ended_
;
446 // Whether or not our embedder has seen a DragSourceEndedAt() call.
447 bool seen_embedder_drag_source_ended_at_
;
449 // Indicates the URL dragged into the guest if any.
452 // Guests generate frames and send a CompositorFrameSwapped (CFS) message
453 // indicating the next frame is ready to be positioned and composited.
454 // Subsequent frames are not generated until the IPC is ACKed. We would like
455 // to ensure that the guest generates frames on attachment so we directly ACK
456 // an unACKed CFS. ACKs could get lost between the time a guest is detached
457 // from a container and the time it is attached elsewhere. This mitigates this
458 // race by ensuring the guest is ACKed on attachment.
459 scoped_ptr
<FrameMsg_CompositorFrameSwapped_Params
> last_pending_frame_
;
461 // This is a queue of messages that are destined to be sent to the embedder
462 // once the guest is attached to a particular embedder.
463 std::deque
<linked_ptr
<IPC::Message
> > pending_messages_
;
465 BrowserPluginGuestDelegate
* const delegate_
;
467 // Weak pointer used to ask GeolocationPermissionContext about geolocation
469 base::WeakPtrFactory
<BrowserPluginGuest
> weak_ptr_factory_
;
471 DISALLOW_COPY_AND_ASSIGN(BrowserPluginGuest
);
474 } // namespace content
476 #endif // CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_H_