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 WebContentsDelegate and WebContentsObserver for the
14 // guest WebContents. BrowserPluginGuest operates under the assumption that the
15 // guest will be 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/id_map.h"
26 #include "base/memory/shared_memory.h"
27 #include "base/memory/weak_ptr.h"
28 #include "base/values.h"
29 #include "content/common/edit_command.h"
30 #include "content/port/common/input_event_ack_state.h"
31 #include "content/public/browser/browser_plugin_guest_delegate.h"
32 #include "content/public/browser/javascript_dialog_manager.h"
33 #include "content/public/browser/web_contents_delegate.h"
34 #include "content/public/browser/web_contents_observer.h"
35 #include "content/public/common/browser_plugin_permission_type.h"
36 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
37 #include "third_party/WebKit/public/web/WebDragOperation.h"
38 #include "third_party/WebKit/public/web/WebDragStatus.h"
39 #include "third_party/WebKit/public/web/WebInputEvent.h"
40 #include "ui/base/ime/text_input_mode.h"
41 #include "ui/base/ime/text_input_type.h"
42 #include "ui/gfx/rect.h"
43 #include "ui/surface/transport_dib.h"
45 struct BrowserPluginHostMsg_AutoSize_Params;
46 struct BrowserPluginHostMsg_Attach_Params;
47 struct BrowserPluginHostMsg_ResizeGuest_Params;
48 struct FrameHostMsg_BuffersSwappedACK_Params;
49 struct FrameHostMsg_CompositorFrameSwappedACK_Params;
50 struct FrameHostMsg_ReclaimCompositorResources_Params;
51 struct ViewHostMsg_CreateWindow_Params;
52 #if defined(OS_MACOSX)
53 struct ViewHostMsg_ShowPopup_Params;
55 struct ViewHostMsg_UpdateRect_Params;
59 class CompositorFrameAck;
76 class BrowserPluginHostFactory;
77 class BrowserPluginEmbedder;
78 class BrowserPluginGuestManager;
79 class RenderProcessHost;
80 class RenderWidgetHostView;
83 struct MediaStreamRequest;
85 // A browser plugin guest provides functionality for WebContents to operate in
86 // the guest role and implements guest-specific overrides for ViewHostMsg_*
89 // When a guest is initially created, it is in an unattached state. That is,
90 // it is not visible anywhere and has no embedder WebContents assigned.
91 // A BrowserPluginGuest is said to be "attached" if it has an embedder.
92 // A BrowserPluginGuest can also create a new unattached guest via
93 // CreateNewWindow. The newly created guest will live in the same partition,
94 // which means it can share storage and can script this guest.
95 class CONTENT_EXPORT BrowserPluginGuest
96 : public JavaScriptDialogManager,
97 public WebContentsDelegate,
98 public WebContentsObserver {
100 typedef base::Callback<void(bool)> GeolocationCallback;
101 virtual ~BrowserPluginGuest();
103 // The WebContents passed into the factory method here has not been
104 // initialized yet and so it does not yet hold a SiteInstance.
105 // BrowserPluginGuest must be constructed and installed into a WebContents
106 // prior to its initialization because WebContents needs to determine what
107 // type of WebContentsView to construct on initialization. The content
108 // embedder needs to be aware of |guest_site_instance| on the guest's
109 // construction and so we pass it in here.
110 static BrowserPluginGuest* Create(
112 SiteInstance* guest_site_instance,
113 WebContentsImpl* web_contents,
114 scoped_ptr<base::DictionaryValue> extra_params);
116 static BrowserPluginGuest* CreateWithOpener(
118 bool has_render_view,
119 WebContentsImpl* web_contents,
120 BrowserPluginGuest* opener);
122 // Returns a WeakPtr to this BrowserPluginGuest.
123 base::WeakPtr<BrowserPluginGuest> AsWeakPtr();
125 // Called when the embedder WebContents is destroyed to give the
126 // BrowserPluginGuest an opportunity to clean up after itself.
127 void EmbedderDestroyed();
129 // Called when the embedder WebContents changes visibility.
130 void EmbedderVisibilityChanged(bool visible);
132 // Destroys the guest WebContents and all its associated state, including
133 // this BrowserPluginGuest, and its new unattached windows.
136 // Returns the identifier that uniquely identifies a browser plugin guest
137 // within an embedder.
138 int instance_id() const { return instance_id_; }
140 bool OnMessageReceivedFromEmbedder(const IPC::Message& message);
142 void Initialize(const BrowserPluginHostMsg_Attach_Params& params,
143 WebContentsImpl* embedder_web_contents);
145 WebContentsImpl* embedder_web_contents() const {
146 return embedder_web_contents_;
149 // Returns the embedder's RenderWidgetHostView if it is available.
150 // Returns NULL otherwise.
151 RenderWidgetHostView* GetEmbedderRenderWidgetHostView();
153 bool focused() const { return focused_; }
154 bool visible() const { return guest_visible_; }
155 void clear_damage_buffer() { damage_buffer_.reset(); }
156 bool is_in_destruction() { return is_in_destruction_; }
158 BrowserPluginGuest* opener() const { return opener_.get(); }
160 // Returns whether the mouse pointer was unlocked.
161 bool UnlockMouseIfNecessary(const NativeWebKeyboardEvent& event);
163 void UpdateVisibility();
165 void CopyFromCompositingSurface(
166 gfx::Rect src_subrect,
168 const base::Callback<void(bool, const SkBitmap&)>& callback);
170 // WebContentsObserver implementation.
171 virtual void DidCommitProvisionalLoadForFrame(
173 const base::string16& frame_unique_name,
176 PageTransition transition_type,
177 RenderViewHost* render_view_host) OVERRIDE;
178 virtual void DidStopLoading(RenderViewHost* render_view_host) OVERRIDE;
180 virtual void RenderViewReady() OVERRIDE;
181 virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
182 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
184 // WebContentsDelegate implementation.
185 virtual bool AddMessageToConsole(WebContents* source,
187 const base::string16& message,
189 const base::string16& source_id) OVERRIDE;
190 // If a new window is created with target="_blank" and rel="noreferrer", then
191 // this method is called, indicating that the new WebContents is ready to be
193 virtual void AddNewContents(WebContents* source,
194 WebContents* new_contents,
195 WindowOpenDisposition disposition,
196 const gfx::Rect& initial_pos,
198 bool* was_blocked) OVERRIDE;
199 virtual void CanDownload(RenderViewHost* render_view_host,
201 const std::string& request_method,
202 const base::Callback<void(bool)>& callback) OVERRIDE;
203 virtual void LoadProgressChanged(WebContents* source,
204 double progress) OVERRIDE;
205 virtual void CloseContents(WebContents* source) OVERRIDE;
206 virtual JavaScriptDialogManager* GetJavaScriptDialogManager() OVERRIDE;
207 virtual bool HandleContextMenu(const ContextMenuParams& params) OVERRIDE;
208 virtual void HandleKeyboardEvent(
210 const NativeWebKeyboardEvent& event) OVERRIDE;
211 virtual WebContents* OpenURLFromTab(WebContents* source,
212 const OpenURLParams& params) OVERRIDE;
213 virtual void WebContentsCreated(WebContents* source_contents,
214 int64 source_frame_id,
215 const base::string16& frame_name,
216 const GURL& target_url,
217 WebContents* new_contents) OVERRIDE;
218 virtual void RendererUnresponsive(WebContents* source) OVERRIDE;
219 virtual void RendererResponsive(WebContents* source) OVERRIDE;
220 virtual void RunFileChooser(WebContents* web_contents,
221 const FileChooserParams& params) OVERRIDE;
222 virtual bool ShouldFocusPageAfterCrash() OVERRIDE;
223 virtual void RequestMediaAccessPermission(
224 WebContents* web_contents,
225 const MediaStreamRequest& request,
226 const MediaResponseCallback& callback) OVERRIDE;
227 virtual bool PreHandleGestureEvent(
228 content::WebContents* source,
229 const blink::WebGestureEvent& event) OVERRIDE;
231 // JavaScriptDialogManager implementation.
232 virtual void RunJavaScriptDialog(
233 WebContents* web_contents,
234 const GURL& origin_url,
235 const std::string& accept_lang,
236 JavaScriptMessageType javascript_message_type,
237 const base::string16& message_text,
238 const base::string16& default_prompt_text,
239 const DialogClosedCallback& callback,
240 bool* did_suppress_message) OVERRIDE;
241 virtual void RunBeforeUnloadDialog(
242 WebContents* web_contents,
243 const base::string16& message_text,
245 const DialogClosedCallback& callback) OVERRIDE;
246 virtual bool HandleJavaScriptDialog(
247 WebContents* web_contents,
249 const base::string16* prompt_override) OVERRIDE;
250 virtual void CancelActiveAndPendingDialogs(
251 WebContents* web_contents) OVERRIDE;
252 virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE;
254 // Exposes the protected web_contents() from WebContentsObserver.
255 WebContentsImpl* GetWebContents();
257 // Overridden in tests.
258 virtual void SetDamageBuffer(
259 const BrowserPluginHostMsg_ResizeGuest_Params& params);
261 gfx::Point GetScreenCoordinates(const gfx::Point& relative_position) const;
263 // Helper to send messages to embedder. This methods fills the message with
264 // the correct routing id.
265 // Overridden in test implementation since we want to intercept certain
266 // messages for testing.
267 virtual void SendMessageToEmbedder(IPC::Message* msg);
269 // Returns whether the guest is attached to an embedder.
270 bool attached() const { return embedder_web_contents_ != NULL; }
272 // Attaches this BrowserPluginGuest to the provided |embedder_web_contents|
273 // and initializes the guest with the provided |params|. Attaching a guest
274 // to an embedder implies that this guest's lifetime is no longer managed
275 // by its opener, and it can begin loading resources. |extra_params| are
276 // parameters passed into BrowserPlugin from JavaScript to be forwarded to
277 // the content embedder.
278 void Attach(WebContentsImpl* embedder_web_contents,
279 BrowserPluginHostMsg_Attach_Params params,
280 const base::DictionaryValue& extra_params);
282 // Requests geolocation permission through Embedder JavaScript API.
283 void AskEmbedderForGeolocationPermission(int bridge_id,
284 const GURL& requesting_frame,
285 const GeolocationCallback& callback);
286 // Cancels pending geolocation request.
287 void CancelGeolocationRequest(int bridge_id);
289 // Allow the embedder to call this for unhandled messages when
290 // BrowserPluginGuest is already destroyed.
291 static void AcknowledgeBufferPresent(int route_id,
293 const gpu::Mailbox& mailbox,
296 // Returns whether BrowserPluginGuest is interested in receiving the given
298 static bool ShouldForwardToBrowserPluginGuest(const IPC::Message& message);
299 gfx::Rect ToGuestRect(const gfx::Rect& rect);
301 void DragSourceEndedAt(int client_x, int client_y, int screen_x,
302 int screen_y, blink::WebDragOperation operation);
304 void DragSourceMovedTo(int client_x, int client_y,
305 int screen_x, int screen_y);
307 // Called when the drag started by this guest ends at an OS-level.
308 void EndSystemDrag();
310 // |this| takes ownership of |delegate|.
311 void SetDelegate(BrowserPluginGuestDelegate* delegate);
313 void RespondToPermissionRequest(int request_id,
315 const std::string& user_input);
317 // Overrides factory for testing. Default (NULL) value indicates regular
318 // (non-test) environment.
319 static void set_factory_for_testing(BrowserPluginHostFactory* factory) {
320 BrowserPluginGuest::factory_ = factory;
323 void SetZoom(double zoom_factor);
326 class EmbedderWebContentsObserver;
327 friend class TestBrowserPluginGuest;
329 class DownloadRequest;
330 class GeolocationRequest;
331 class JavaScriptDialogRequest;
332 // MediaRequest because of naming conflicts with MediaStreamRequest.
334 class NewWindowRequest;
335 class PermissionRequest;
336 class PointerLockRequest;
338 // Tracks the name, and target URL of the new window and whether or not it has
339 // changed since the WebContents has been created and before the new window
340 // has been attached to a BrowserPlugin. Once the first navigation commits, we
341 // no longer track this information.
342 struct NewWindowInfo {
346 NewWindowInfo(const GURL& url, const std::string& name) :
352 // BrowserPluginGuest is a WebContentsObserver of |web_contents| and
353 // |web_contents| has to stay valid for the lifetime of BrowserPluginGuest.
354 BrowserPluginGuest(int instance_id,
355 bool has_render_view,
356 WebContentsImpl* web_contents,
357 BrowserPluginGuest* opener);
359 // Destroy unattached new windows that have been opened by this
360 // BrowserPluginGuest.
361 void DestroyUnattachedWindows();
363 void LoadURLWithParams(const GURL& url,
364 const Referrer& referrer,
365 PageTransition transition_type,
366 WebContents* web_contents);
368 // Bridge IDs correspond to a geolocation request. This method will remove
369 // the bookkeeping for a particular geolocation request associated with the
370 // provided |bridge_id|. It returns the request ID of the geolocation request.
371 int RemoveBridgeID(int bridge_id);
373 // Returns the |request_id| generated for the |request| provided.
374 int RequestPermission(
375 BrowserPluginPermissionType permission_type,
376 scoped_refptr<BrowserPluginGuest::PermissionRequest> request,
377 const base::DictionaryValue& request_info);
379 // Creates a new guest window, and BrowserPluginGuest that is owned by this
380 // BrowserPluginGuest.
381 BrowserPluginGuest* CreateNewGuestWindow(const OpenURLParams& params);
383 base::SharedMemory* damage_buffer() const { return damage_buffer_.get(); }
384 const gfx::Size& damage_view_size() const { return damage_view_size_; }
385 float damage_buffer_scale_factor() const {
386 return damage_buffer_scale_factor_;
388 // Returns the damage buffer corresponding to the handle in resize |params|.
389 base::SharedMemory* GetDamageBufferFromEmbedder(
390 const BrowserPluginHostMsg_ResizeGuest_Params& params);
392 bool InAutoSizeBounds(const gfx::Size& size) const;
394 void RequestNewWindowPermission(WindowOpenDisposition disposition,
395 const gfx::Rect& initial_bounds,
397 WebContentsImpl* new_contents);
399 // Message handlers for messages from embedder.
401 void OnCompositorFrameSwappedACK(
403 const FrameHostMsg_CompositorFrameSwappedACK_Params& params);
404 void OnCopyFromCompositingSurfaceAck(int instance_id,
406 const SkBitmap& bitmap);
407 // Handles drag events from the embedder.
408 // When dragging, the drag events go to the embedder first, and if the drag
409 // happens on the browser plugin, then the plugin sends a corresponding
410 // drag-message to the guest. This routes the drag-message to the guest
412 void OnDragStatusUpdate(int instance_id,
413 blink::WebDragStatus drag_status,
414 const DropData& drop_data,
415 blink::WebDragOperationsMask drag_mask,
416 const gfx::Point& location);
417 // Instructs the guest to execute an edit command decoded in the embedder.
418 void OnExecuteEditCommand(int instance_id,
419 const std::string& command);
421 // Returns compositor resources reclaimed in the embedder to the guest.
422 void OnReclaimCompositorResources(
424 const FrameHostMsg_ReclaimCompositorResources_Params& params);
426 // Overriden in tests.
427 virtual void OnHandleInputEvent(int instance_id,
428 const gfx::Rect& guest_window_rect,
429 const blink::WebInputEvent* event);
430 void OnLockMouse(bool user_gesture,
431 bool last_unlocked_by_target,
433 void OnLockMouseAck(int instance_id, bool succeeded);
434 void OnNavigateGuest(int instance_id, const std::string& src);
435 void OnPluginDestroyed(int instance_id);
436 // Grab the new damage buffer from the embedder, and resize the guest's
438 void OnResizeGuest(int instance_id,
439 const BrowserPluginHostMsg_ResizeGuest_Params& params);
440 // Overriden in tests.
441 virtual void OnSetFocus(int instance_id, bool focused);
442 // Sets the name of the guest so that other guests in the same partition can
444 void OnSetName(int instance_id, const std::string& name);
445 // Updates the size state of the guest.
448 const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
449 const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params);
450 void OnSetEditCommandsForNextKeyEvent(
452 const std::vector<EditCommand>& edit_commands);
453 void OnSetContentsOpaque(int instance_id, bool opaque);
454 // The guest WebContents is visible if both its embedder is visible and
455 // the browser plugin element is visible. If either one is not then the
456 // WebContents is marked as hidden. A hidden WebContents will consume
457 // fewer GPU and CPU resources.
459 // When every WebContents in a RenderProcessHost is hidden, it will lower
460 // the priority of the process (see RenderProcessHostImpl::WidgetHidden).
462 // It will also send a message to the guest renderer process to cleanup
463 // resources such as dropping back buffers and adjusting memory limits (if in
464 // compositing mode, see CCLayerTreeHost::setVisible).
466 // Additionally, it will slow down Javascript execution and garbage
467 // collection. See RenderThreadImpl::IdleHandler (executed when hidden) and
468 // RenderThreadImpl::IdleHandlerInForegroundTab (executed when visible).
469 void OnSetVisibility(int instance_id, bool visible);
470 // Message from embedder acknowledging last HW buffer.
471 void OnSwapBuffersACK(int instance_id,
472 const FrameHostMsg_BuffersSwappedACK_Params& params);
473 void OnUnlockMouse();
474 void OnUnlockMouseAck(int instance_id);
475 void OnUpdateGeometry(int instance_id, const gfx::Rect& view_rect);
476 void OnUpdateRectACK(
479 const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
480 const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params);
482 void OnTextInputTypeChanged(ui::TextInputType type,
483 ui::TextInputMode input_mode,
484 bool can_compose_inline);
485 void OnImeSetComposition(
487 const std::string& text,
488 const std::vector<blink::WebCompositionUnderline>& underlines,
491 void OnImeConfirmComposition(
493 const std::string& text,
494 bool keep_selection);
495 void OnExtendSelectionAndDelete(int instance_id, int before, int after);
496 // Overridden in tests.
497 virtual void OnImeCancelComposition();
498 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
499 void OnImeCompositionRangeChanged(
500 const gfx::Range& range,
501 const std::vector<gfx::Rect>& character_bounds);
504 // Message handlers for messages from guest.
506 void OnDragStopped();
507 void OnHandleInputEventAck(
508 blink::WebInputEvent::Type event_type,
509 InputEventAckState ack_result);
510 void OnHasTouchEventHandlers(bool accept);
511 void OnSetCursor(const WebCursor& cursor);
512 // On MacOSX popups are painted by the browser process. We handle them here
513 // so that they are positioned correctly.
514 #if defined(OS_MACOSX)
515 void OnShowPopup(const ViewHostMsg_ShowPopup_Params& params);
517 void OnShowWidget(int route_id, const gfx::Rect& initial_pos);
518 // Overriden in tests.
519 virtual void OnTakeFocus(bool reverse);
520 void OnUpdateFrameName(int frame_id,
522 const std::string& name);
523 void OnUpdateRect(const ViewHostMsg_UpdateRect_Params& params);
525 // Requests download permission through embedder JavaScript API after
526 // retrieving url information from IO thread.
527 void DidRetrieveDownloadURLFromRequestId(
528 const std::string& request_method,
529 const base::Callback<void(bool)>& callback,
530 const std::string& url);
532 // Embedder sets permission to allow or deny geolocation request.
533 void SetGeolocationPermission(
534 GeolocationCallback callback, int bridge_id, bool allowed);
536 // Forwards all messages from the |pending_messages_| queue to the embedder.
537 void SendQueuedMessages();
539 // Static factory instance (always NULL for non-test).
540 static BrowserPluginHostFactory* factory_;
542 scoped_ptr<EmbedderWebContentsObserver> embedder_web_contents_observer_;
543 WebContentsImpl* embedder_web_contents_;
545 std::map<int, int> bridge_id_to_request_id_map_;
547 // An identifier that uniquely identifies a browser plugin guest within an
550 scoped_ptr<base::SharedMemory> damage_buffer_;
551 // An identifier that uniquely identifies a damage buffer.
552 uint32 damage_buffer_sequence_id_;
553 size_t damage_buffer_size_;
554 gfx::Size damage_view_size_;
555 float damage_buffer_scale_factor_;
556 float guest_device_scale_factor_;
557 gfx::Rect guest_window_rect_;
558 gfx::Rect guest_screen_rect_;
559 base::TimeDelta guest_hang_timeout_;
562 bool pending_lock_request_;
565 bool embedder_visible_;
567 bool auto_size_enabled_;
568 gfx::Size max_auto_size_;
569 gfx::Size min_auto_size_;
571 // Each copy-request is identified by a unique number. The unique number is
572 // used to keep track of the right callback.
573 int copy_request_id_;
574 typedef base::Callback<void(bool, const SkBitmap&)> CopyRequestCallback;
575 typedef std::map<int, const CopyRequestCallback> CopyRequestMap;
576 CopyRequestMap copy_request_callbacks_;
578 typedef std::map<BrowserPluginGuest*, NewWindowInfo> PendingWindowMap;
579 PendingWindowMap pending_new_windows_;
580 base::WeakPtr<BrowserPluginGuest> opener_;
581 // A counter to generate a unique request id for a permission request.
582 // We only need the ids to be unique for a given BrowserPluginGuest.
583 int next_permission_request_id_;
585 // A map to store relevant info for a request keyed by the request's id.
586 typedef std::map<int, scoped_refptr<PermissionRequest> > RequestMap;
587 RequestMap permission_request_map_;
589 // Indicates that this BrowserPluginGuest has associated renderer-side state.
590 // This is used to determine whether or not to create a new RenderView when
591 // this guest is attached.
592 bool has_render_view_;
594 // Last seen size of guest contents (by OnUpdateRect).
595 gfx::Size last_seen_view_size_;
596 // Last seen autosize attribute state (by OnUpdateRect).
597 bool last_seen_auto_size_enabled_;
599 bool is_in_destruction_;
601 // Text input type states.
602 ui::TextInputType last_text_input_type_;
603 ui::TextInputMode last_input_mode_;
604 bool last_can_compose_inline_;
606 // This is a queue of messages that are destined to be sent to the embedder
607 // once the guest is attached to a particular embedder.
608 std::queue<IPC::Message*> pending_messages_;
610 scoped_ptr<BrowserPluginGuestDelegate> delegate_;
612 // These are parameters passed from JavaScript on attachment to the content
614 scoped_ptr<base::DictionaryValue> extra_attach_params_;
616 // Weak pointer used to ask GeolocationPermissionContext about geolocation
618 base::WeakPtrFactory<BrowserPluginGuest> weak_ptr_factory_;
620 DISALLOW_COPY_AND_ASSIGN(BrowserPluginGuest);
623 } // namespace content
625 #endif // CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_H_