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/WebDragOperation.h"
37 #include "third_party/WebKit/public/web/WebDragStatus.h"
38 #include "third_party/WebKit/public/web/WebInputEvent.h"
39 #include "ui/gfx/rect.h"
40 #include "ui/surface/transport_dib.h"
42 struct BrowserPluginHostMsg_AutoSize_Params;
43 struct BrowserPluginHostMsg_Attach_Params;
44 struct BrowserPluginHostMsg_ResizeGuest_Params;
45 struct ViewHostMsg_CreateWindow_Params;
46 #if defined(OS_MACOSX)
47 struct ViewHostMsg_ShowPopup_Params;
49 struct ViewHostMsg_UpdateRect_Params;
53 class CompositorFrameAck;
62 class BrowserPluginHostFactory;
63 class BrowserPluginEmbedder;
64 class BrowserPluginGuestManager;
65 class RenderProcessHost;
66 class RenderWidgetHostView;
69 struct MediaStreamRequest;
71 // A browser plugin guest provides functionality for WebContents to operate in
72 // the guest role and implements guest-specific overrides for ViewHostMsg_*
75 // When a guest is initially created, it is in an unattached state. That is,
76 // it is not visible anywhere and has no embedder WebContents assigned.
77 // A BrowserPluginGuest is said to be "attached" if it has an embedder.
78 // A BrowserPluginGuest can also create a new unattached guest via
79 // CreateNewWindow. The newly created guest will live in the same partition,
80 // which means it can share storage and can script this guest.
81 class CONTENT_EXPORT BrowserPluginGuest
82 : public JavaScriptDialogManager,
83 public WebContentsDelegate,
84 public WebContentsObserver,
85 public base::SupportsWeakPtr<BrowserPluginGuest> {
87 typedef base::Callback<void(bool)> GeolocationCallback;
88 virtual ~BrowserPluginGuest();
90 // The WebContents passed into the factory method here has not been
91 // initialized yet and so it does not yet hold a SiteInstance.
92 // BrowserPluginGuest must be constructed and installed into a WebContents
93 // prior to its initialization because WebContents needs to determine what
94 // type of WebContentsView to construct on initialization. The content
95 // embedder needs to be aware of |guest_site_instance| on the guest's
96 // construction and so we pass it in here.
97 static BrowserPluginGuest* Create(
99 SiteInstance* guest_site_instance,
100 WebContentsImpl* web_contents,
101 scoped_ptr<base::DictionaryValue> extra_params);
103 static BrowserPluginGuest* CreateWithOpener(
105 WebContentsImpl* web_contents,
106 BrowserPluginGuest* opener,
107 bool has_render_view);
109 // Called when the embedder WebContents is destroyed to give the
110 // BrowserPluginGuest an opportunity to clean up after itself.
111 void EmbedderDestroyed();
113 // Called when the embedder WebContents changes visibility.
114 void EmbedderVisibilityChanged(bool visible);
116 // Destroys the guest WebContents and all its associated state, including
117 // this BrowserPluginGuest, and its new unattached windows.
120 // Returns the identifier that uniquely identifies a browser plugin guest
121 // within an embedder.
122 int instance_id() const { return instance_id_; }
124 // Overrides factory for testing. Default (NULL) value indicates regular
125 // (non-test) environment.
126 static void set_factory_for_testing(BrowserPluginHostFactory* factory) {
127 BrowserPluginGuest::factory_ = factory;
130 bool OnMessageReceivedFromEmbedder(const IPC::Message& message);
132 void Initialize(WebContentsImpl* embedder_web_contents,
133 const BrowserPluginHostMsg_Attach_Params& params);
135 void set_guest_hang_timeout_for_testing(const base::TimeDelta& timeout) {
136 guest_hang_timeout_ = timeout;
139 WebContentsImpl* embedder_web_contents() const {
140 return embedder_web_contents_;
143 RenderWidgetHostView* GetEmbedderRenderWidgetHostView();
145 bool focused() const { return focused_; }
146 bool visible() const { return guest_visible_; }
147 void clear_damage_buffer() { damage_buffer_.reset(); }
148 bool is_in_destruction() { return is_in_destruction_; }
150 BrowserPluginGuest* opener() const { return opener_.get(); }
152 // Returns whether the mouse pointer was unlocked.
153 bool UnlockMouseIfNecessary(const NativeWebKeyboardEvent& event);
155 void UpdateVisibility();
157 // WebContentsObserver implementation.
158 virtual void DidCommitProvisionalLoadForFrame(
160 const string16& frame_unique_name,
163 PageTransition transition_type,
164 RenderViewHost* render_view_host) OVERRIDE;
165 virtual void DidStopLoading(RenderViewHost* render_view_host) OVERRIDE;
167 virtual void RenderViewReady() OVERRIDE;
168 virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
169 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
171 // WebContentsDelegate implementation.
172 virtual bool AddMessageToConsole(WebContents* source,
174 const string16& message,
176 const string16& source_id) OVERRIDE;
177 // If a new window is created with target="_blank" and rel="noreferrer", then
178 // this method is called, indicating that the new WebContents is ready to be
180 virtual void AddNewContents(WebContents* source,
181 WebContents* new_contents,
182 WindowOpenDisposition disposition,
183 const gfx::Rect& initial_pos,
185 bool* was_blocked) OVERRIDE;
186 virtual void CanDownload(RenderViewHost* render_view_host,
188 const std::string& request_method,
189 const base::Callback<void(bool)>& callback) OVERRIDE;
190 virtual void LoadProgressChanged(WebContents* source,
191 double progress) OVERRIDE;
192 virtual void CloseContents(WebContents* source) OVERRIDE;
193 virtual JavaScriptDialogManager* GetJavaScriptDialogManager() OVERRIDE;
194 virtual bool HandleContextMenu(const ContextMenuParams& params) OVERRIDE;
195 virtual void HandleKeyboardEvent(
197 const NativeWebKeyboardEvent& event) OVERRIDE;
198 virtual WebContents* OpenURLFromTab(WebContents* source,
199 const OpenURLParams& params) OVERRIDE;
200 virtual void WebContentsCreated(WebContents* source_contents,
201 int64 source_frame_id,
202 const string16& frame_name,
203 const GURL& target_url,
204 WebContents* new_contents) OVERRIDE;
205 virtual void RendererUnresponsive(WebContents* source) OVERRIDE;
206 virtual void RendererResponsive(WebContents* source) OVERRIDE;
207 virtual void RunFileChooser(WebContents* web_contents,
208 const FileChooserParams& params) OVERRIDE;
209 virtual bool ShouldFocusPageAfterCrash() OVERRIDE;
210 virtual void RequestMediaAccessPermission(
211 WebContents* web_contents,
212 const MediaStreamRequest& request,
213 const MediaResponseCallback& callback) OVERRIDE;
215 // JavaScriptDialogManager implementation.
216 virtual void RunJavaScriptDialog(
217 WebContents* web_contents,
218 const GURL& origin_url,
219 const std::string& accept_lang,
220 JavaScriptMessageType javascript_message_type,
221 const string16& message_text,
222 const string16& default_prompt_text,
223 const DialogClosedCallback& callback,
224 bool* did_suppress_message) OVERRIDE;
225 virtual void RunBeforeUnloadDialog(
226 WebContents* web_contents,
227 const string16& message_text,
229 const DialogClosedCallback& callback) OVERRIDE;
230 virtual bool HandleJavaScriptDialog(WebContents* web_contents,
232 const string16* prompt_override) OVERRIDE;
233 virtual void CancelActiveAndPendingDialogs(
234 WebContents* web_contents) OVERRIDE;
235 virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE;
237 // Exposes the protected web_contents() from WebContentsObserver.
238 WebContentsImpl* GetWebContents();
240 // Overridden in tests.
241 virtual void SetDamageBuffer(
242 const BrowserPluginHostMsg_ResizeGuest_Params& params);
244 gfx::Point GetScreenCoordinates(const gfx::Point& relative_position) const;
246 // Helper to send messages to embedder. This methods fills the message with
247 // the correct routing id.
248 // Overridden in test implementation since we want to intercept certain
249 // messages for testing.
250 virtual void SendMessageToEmbedder(IPC::Message* msg);
252 // Returns whether the guest is attached to an embedder.
253 bool attached() const { return !!embedder_web_contents_; }
255 // Attaches this BrowserPluginGuest to the provided |embedder_web_contents|
256 // and initializes the guest with the provided |params|. Attaching a guest
257 // to an embedder implies that this guest's lifetime is no longer managed
258 // by its opener, and it can begin loading resources. |extra_params| are
259 // parameters passed into BrowserPlugin from JavaScript to be forwarded to
260 // the content embedder.
261 void Attach(WebContentsImpl* embedder_web_contents,
262 BrowserPluginHostMsg_Attach_Params params,
263 const base::DictionaryValue& extra_params);
265 // Requests geolocation permission through Embedder JavaScript API.
266 void AskEmbedderForGeolocationPermission(int bridge_id,
267 const GURL& requesting_frame,
268 const GeolocationCallback& callback);
269 // Cancels pending geolocation request.
270 void CancelGeolocationRequest(int bridge_id);
272 // Allow the embedder to call this for unhandled messages when
273 // BrowserPluginGuest is already destroyed.
274 static void AcknowledgeBufferPresent(int route_id,
276 const std::string& mailbox_name,
279 // Returns whether BrowserPluginGuest is interested in receiving the given
281 static bool ShouldForwardToBrowserPluginGuest(const IPC::Message& message);
282 gfx::Rect ToGuestRect(const gfx::Rect& rect);
284 void DragSourceEndedAt(int client_x, int client_y, int screen_x,
285 int screen_y, WebKit::WebDragOperation operation);
287 void DragSourceMovedTo(int client_x, int client_y,
288 int screen_x, int screen_y);
290 // Called when the drag started by this guest ends at an OS-level.
291 void EndSystemDrag();
293 // |this| takes ownership of |delegate|.
294 void SetDelegate(BrowserPluginGuestDelegate* delegate);
296 void RespondToPermissionRequest(int request_id,
298 const std::string& user_input);
301 class EmbedderWebContentsObserver;
302 friend class TestBrowserPluginGuest;
304 class DownloadRequest;
305 class GeolocationRequest;
306 class JavaScriptDialogRequest;
307 // MediaRequest because of naming conflicts with MediaStreamRequest.
309 class NewWindowRequest;
310 class PermissionRequest;
311 class PointerLockRequest;
313 BrowserPluginGuest(int instance_id,
314 WebContentsImpl* web_contents,
315 BrowserPluginGuest* opener,
316 bool has_render_view);
318 // Destroy unattached new windows that have been opened by this
319 // BrowserPluginGuest.
320 void DestroyUnattachedWindows();
322 void LoadURLWithParams(WebContents* web_contents,
324 const Referrer& referrer,
325 PageTransition transition_type);
327 // Bridge IDs correspond to a geolocation request. This method will remove
328 // the bookkeeping for a particular geolocation request associated with the
329 // provided |bridge_id|. It returns the request ID of the geolocation request.
330 int RemoveBridgeID(int bridge_id);
332 // Returns the |request_id| generated for the |request| provided.
333 int RequestPermission(
334 BrowserPluginPermissionType permission_type,
335 scoped_refptr<BrowserPluginGuest::PermissionRequest> request,
336 const base::DictionaryValue& request_info);
338 // Creates a new guest window, and BrowserPluginGuest that is owned by this
339 // BrowserPluginGuest.
340 BrowserPluginGuest* CreateNewGuestWindow(const OpenURLParams& params);
342 base::SharedMemory* damage_buffer() const { return damage_buffer_.get(); }
343 const gfx::Size& damage_view_size() const { return damage_view_size_; }
344 float damage_buffer_scale_factor() const {
345 return damage_buffer_scale_factor_;
347 // Returns the damage buffer corresponding to the handle in resize |params|.
348 base::SharedMemory* GetDamageBufferFromEmbedder(
349 const BrowserPluginHostMsg_ResizeGuest_Params& params);
351 bool InAutoSizeBounds(const gfx::Size& size) const;
353 void RequestNewWindowPermission(WebContentsImpl* new_contents,
354 WindowOpenDisposition disposition,
355 const gfx::Rect& initial_bounds,
358 // Message handlers for messages from embedder.
360 void OnCompositorFrameACK(int instance_id,
362 uint32 output_surface_id,
363 int renderer_host_id,
364 const cc::CompositorFrameAck& ack);
366 // Handles drag events from the embedder.
367 // When dragging, the drag events go to the embedder first, and if the drag
368 // happens on the browser plugin, then the plugin sends a corresponding
369 // drag-message to the guest. This routes the drag-message to the guest
371 void OnDragStatusUpdate(int instance_id,
372 WebKit::WebDragStatus drag_status,
373 const DropData& drop_data,
374 WebKit::WebDragOperationsMask drag_mask,
375 const gfx::Point& location);
376 // Instructs the guest to execute an edit command decoded in the embedder.
377 void OnExecuteEditCommand(int instance_id,
378 const std::string& command);
379 // Overriden in tests.
380 virtual void OnHandleInputEvent(int instance_id,
381 const gfx::Rect& guest_window_rect,
382 const WebKit::WebInputEvent* event);
383 void OnLockMouse(bool user_gesture,
384 bool last_unlocked_by_target,
386 void OnLockMouseAck(int instance_id, bool succeeded);
387 void OnNavigateGuest(int instance_id, const std::string& src);
388 void OnPluginDestroyed(int instance_id);
389 // Grab the new damage buffer from the embedder, and resize the guest's
391 void OnResizeGuest(int instance_id,
392 const BrowserPluginHostMsg_ResizeGuest_Params& params);
393 // Overriden in tests.
394 virtual void OnSetFocus(int instance_id, bool focused);
395 // Sets the name of the guest so that other guests in the same partition can
397 void OnSetName(int instance_id, const std::string& name);
398 // Updates the size state of the guest.
401 const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
402 const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params);
403 void OnSetEditCommandsForNextKeyEvent(
405 const std::vector<EditCommand>& edit_commands);
406 // The guest WebContents is visible if both its embedder is visible and
407 // the browser plugin element is visible. If either one is not then the
408 // WebContents is marked as hidden. A hidden WebContents will consume
409 // fewer GPU and CPU resources.
411 // When every WebContents in a RenderProcessHost is hidden, it will lower
412 // the priority of the process (see RenderProcessHostImpl::WidgetHidden).
414 // It will also send a message to the guest renderer process to cleanup
415 // resources such as dropping back buffers and adjusting memory limits (if in
416 // compositing mode, see CCLayerTreeHost::setVisible).
418 // Additionally, it will slow down Javascript execution and garbage
419 // collection. See RenderThreadImpl::IdleHandler (executed when hidden) and
420 // RenderThreadImpl::IdleHandlerInForegroundTab (executed when visible).
421 void OnSetVisibility(int instance_id, bool visible);
422 // Message from embedder acknowledging last HW buffer.
423 void OnSwapBuffersACK(int instance_id,
426 const std::string& mailbox_name,
428 void OnUnlockMouse();
429 void OnUnlockMouseAck(int instance_id);
430 void OnUpdateGeometry(int instance_id, const gfx::Rect& view_rect);
431 void OnUpdateRectACK(
434 const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
435 const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params);
438 // Message handlers for messages from guest.
440 void OnDragStopped();
441 void OnHandleInputEventAck(
442 WebKit::WebInputEvent::Type event_type,
443 InputEventAckState ack_result);
444 void OnHasTouchEventHandlers(bool accept);
445 void OnSetCursor(const WebCursor& cursor);
446 // On MacOSX popups are painted by the browser process. We handle them here
447 // so that they are positioned correctly.
448 #if defined(OS_MACOSX)
449 void OnShowPopup(const ViewHostMsg_ShowPopup_Params& params);
451 void OnShowWidget(int route_id, const gfx::Rect& initial_pos);
452 // Overriden in tests.
453 virtual void OnTakeFocus(bool reverse);
454 void OnUpdateFrameName(int frame_id,
456 const std::string& name);
457 void OnUpdateRect(const ViewHostMsg_UpdateRect_Params& params);
459 // Requests download permission through embedder JavaScript API after
460 // retrieving url information from IO thread.
461 void DidRetrieveDownloadURLFromRequestId(
462 const std::string& request_method,
463 const base::Callback<void(bool)>& callback,
464 const std::string& url);
466 // Embedder sets permission to allow or deny geolocation request.
467 void SetGeolocationPermission(
468 GeolocationCallback callback, int bridge_id, bool allowed);
470 // Forwards all messages from the |pending_messages_| queue to the embedder.
471 void SendQueuedMessages();
473 // Weak pointer used to ask GeolocationPermissionContext about geolocation
475 base::WeakPtrFactory<BrowserPluginGuest> weak_ptr_factory_;
477 // Static factory instance (always NULL for non-test).
478 static BrowserPluginHostFactory* factory_;
480 scoped_ptr<EmbedderWebContentsObserver> embedder_web_contents_observer_;
481 WebContentsImpl* embedder_web_contents_;
483 std::map<int, int> bridge_id_to_request_id_map_;
485 // An identifier that uniquely identifies a browser plugin guest within an
488 scoped_ptr<base::SharedMemory> damage_buffer_;
489 // An identifier that uniquely identifies a damage buffer.
490 uint32 damage_buffer_sequence_id_;
491 size_t damage_buffer_size_;
492 gfx::Size damage_view_size_;
493 float damage_buffer_scale_factor_;
494 float guest_device_scale_factor_;
495 gfx::Rect guest_window_rect_;
496 gfx::Rect guest_screen_rect_;
497 base::TimeDelta guest_hang_timeout_;
500 bool pending_lock_request_;
502 bool embedder_visible_;
504 bool auto_size_enabled_;
505 gfx::Size max_auto_size_;
506 gfx::Size min_auto_size_;
508 // Tracks the name, and target URL of the new window and whether or not it has
509 // changed since the WebContents has been created and before the new window
510 // has been attached to a BrowserPlugin. Once the first navigation commits, we
511 // no longer track this information.
512 struct NewWindowInfo {
516 NewWindowInfo(const GURL& url, const std::string& name) :
521 typedef std::map<BrowserPluginGuest*, NewWindowInfo> PendingWindowMap;
522 PendingWindowMap pending_new_windows_;
523 base::WeakPtr<BrowserPluginGuest> opener_;
524 // A counter to generate a unique request id for a permission request.
525 // We only need the ids to be unique for a given BrowserPluginGuest.
526 int next_permission_request_id_;
528 // A map to store relevant info for a request keyed by the request's id.
529 typedef std::map<int, scoped_refptr<PermissionRequest> > RequestMap;
530 RequestMap permission_request_map_;
532 // Indicates that this BrowserPluginGuest has associated renderer-side state.
533 // This is used to determine whether or not to create a new RenderView when
534 // this guest is attached.
535 bool has_render_view_;
537 // Last seen size of guest contents (by OnUpdateRect).
538 gfx::Size last_seen_view_size_;
539 // Last seen autosize attribute state (by OnUpdateRect).
540 bool last_seen_auto_size_enabled_;
542 bool is_in_destruction_;
544 // This is a queue of messages that are destined to be sent to the embedder
545 // once the guest is attached to a particular embedder.
546 std::queue<IPC::Message*> pending_messages_;
548 scoped_ptr<BrowserPluginGuestDelegate> delegate_;
550 // These are parameters passed from JavaScript on attachment to the content
552 scoped_ptr<base::DictionaryValue> extra_attach_params_;
554 DISALLOW_COPY_AND_ASSIGN(BrowserPluginGuest);
557 } // namespace content
559 #endif // CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_H_