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. 4 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. 8 // 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. 12 // 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. 17 18 #ifndef CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_H_ 19 #define CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_H_ 20 21 #include <map> 22 #include <queue> 23 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/web_contents_observer.h" 32 #include "third_party/WebKit/public/web/WebCompositionUnderline.h" 33 #include "third_party/WebKit/public/web/WebDragOperation.h" 34 #include "third_party/WebKit/public/web/WebDragStatus.h" 35 #include "third_party/WebKit/public/web/WebInputEvent.h" 36 #include "ui/base/ime/text_input_mode.h" 37 #include "ui/base/ime/text_input_type.h" 38 #include "ui/gfx/rect.h" 39 40 class SkBitmap; 41 struct BrowserPluginHostMsg_Attach_Params; 42 struct BrowserPluginHostMsg_ResizeGuest_Params; 43 struct FrameHostMsg_CompositorFrameSwappedACK_Params; 44 struct FrameHostMsg_ReclaimCompositorResources_Params; 45 #if defined(OS_MACOSX) 46 struct FrameHostMsg_ShowPopup_Params; 47 #endif 48 49 namespace blink { 50 class WebInputEvent; 51 } // namespace blink 52 53 namespace cc { 54 class CompositorFrame; 55 } // namespace cc 56 57 namespace gfx { 58 class Range; 59 } // namespace gfx 60 61 namespace content { 62 63 class BrowserPluginGuestManager; 64 class RenderViewHostImpl; 65 class RenderWidgetHost; 66 class RenderWidgetHostView; 67 class SiteInstance; 68 struct DropData; 69 70 // A browser plugin guest provides functionality for WebContents to operate in 71 // the guest role and implements guest-specific overrides for ViewHostMsg_* 72 // messages. 73 // 74 // When a guest is initially created, it is in an unattached state. That is, 75 // it is not visible anywhere and has no embedder WebContents assigned. 76 // A BrowserPluginGuest is said to be "attached" if it has an embedder. 77 // A BrowserPluginGuest can also create a new unattached guest via 78 // CreateNewWindow. The newly created guest will live in the same partition, 79 // which means it can share storage and can script this guest. 80 class CONTENT_EXPORT BrowserPluginGuest : public WebContentsObserver { 81 public: 82 virtual ~BrowserPluginGuest(); 83 84 // The WebContents passed into the factory method here has not been 85 // initialized yet and so it does not yet hold a SiteInstance. 86 // BrowserPluginGuest must be constructed and installed into a WebContents 87 // prior to its initialization because WebContents needs to determine what 88 // type of WebContentsView to construct on initialization. The content 89 // embedder needs to be aware of |guest_site_instance| on the guest's 90 // construction and so we pass it in here. 91 static BrowserPluginGuest* Create(WebContentsImpl* web_contents, 92 BrowserPluginGuestDelegate* delegate); 93 94 // Returns whether the given WebContents is a BrowserPlugin guest. 95 static bool IsGuest(WebContentsImpl* web_contents); 96 97 // Returns whether the given RenderviewHost is a BrowserPlugin guest. 98 static bool IsGuest(RenderViewHostImpl* render_view_host); 99 100 // Returns a WeakPtr to this BrowserPluginGuest. 101 base::WeakPtr<BrowserPluginGuest> AsWeakPtr(); 102 103 // Sets the focus state of the current RenderWidgetHostView. 104 void SetFocus(RenderWidgetHost* rwh, bool focused); 105 106 // Sets the lock state of the pointer. Returns true if |allowed| is true and 107 // the mouse has been successfully locked. 108 bool LockMouse(bool allowed); 109 110 // Return true if the mouse is locked. mouse_locked()111 bool mouse_locked() const { return mouse_locked_; } 112 113 // Called when the embedder WebContents changes visibility. 114 void EmbedderVisibilityChanged(bool visible); 115 116 // Destroys the guest WebContents and all its associated state, including 117 // this BrowserPluginGuest, and its new unattached windows. 118 void Destroy(); 119 120 // Creates a new guest WebContentsImpl with the provided |params| with |this| 121 // as the |opener|. 122 WebContentsImpl* CreateNewGuestWindow( 123 const WebContents::CreateParams& params); 124 125 // Returns the identifier that uniquely identifies a browser plugin guest 126 // within an embedder. browser_plugin_instance_id()127 int browser_plugin_instance_id() const { return browser_plugin_instance_id_; } 128 129 bool OnMessageReceivedFromEmbedder(const IPC::Message& message); 130 embedder_web_contents()131 WebContentsImpl* embedder_web_contents() const { 132 return embedder_web_contents_; 133 } 134 135 // Returns the embedder's RenderWidgetHostView if it is available. 136 // Returns NULL otherwise. 137 RenderWidgetHostView* GetEmbedderRenderWidgetHostView(); 138 focused()139 bool focused() const { return focused_; } visible()140 bool visible() const { return guest_visible_; } is_in_destruction()141 bool is_in_destruction() { return is_in_destruction_; } 142 143 void UpdateVisibility(); 144 145 void CopyFromCompositingSurface( 146 gfx::Rect src_subrect, 147 gfx::Size dst_size, 148 const base::Callback<void(bool, const SkBitmap&)>& callback); 149 150 BrowserPluginGuestManager* GetBrowserPluginGuestManager() const; 151 152 // WebContentsObserver implementation. 153 virtual void DidCommitProvisionalLoadForFrame( 154 RenderFrameHost* render_frame_host, 155 const GURL& url, 156 ui::PageTransition transition_type) OVERRIDE; 157 158 virtual void RenderViewReady() OVERRIDE; 159 virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE; 160 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; 161 virtual bool OnMessageReceived(const IPC::Message& message, 162 RenderFrameHost* render_frame_host) OVERRIDE; 163 164 // Exposes the protected web_contents() from WebContentsObserver. 165 WebContentsImpl* GetWebContents() const; 166 167 gfx::Point GetScreenCoordinates(const gfx::Point& relative_position) const; 168 169 // Helper to send messages to embedder. This methods fills the message with 170 // the correct routing id. 171 void SendMessageToEmbedder(IPC::Message* msg); 172 173 // Returns whether the guest is attached to an embedder. attached()174 bool attached() const { return embedder_web_contents_ != NULL; } 175 176 // Attaches this BrowserPluginGuest to the provided |embedder_web_contents| 177 // and initializes the guest with the provided |params|. Attaching a guest 178 // to an embedder implies that this guest's lifetime is no longer managed 179 // by its opener, and it can begin loading resources. 180 void Attach(int browser_plugin_instance_id, 181 WebContentsImpl* embedder_web_contents, 182 const BrowserPluginHostMsg_Attach_Params& params); 183 184 // Returns whether BrowserPluginGuest is interested in receiving the given 185 // |message|. 186 static bool ShouldForwardToBrowserPluginGuest(const IPC::Message& message); 187 188 void DragSourceEndedAt(int client_x, int client_y, int screen_x, 189 int screen_y, blink::WebDragOperation operation); 190 191 // Called when the drag started by this guest ends at an OS-level. 192 void EndSystemDrag(); 193 194 void RespondToPermissionRequest(int request_id, 195 bool should_allow, 196 const std::string& user_input); 197 198 void PointerLockPermissionResponse(bool allow); 199 200 void SwapCompositorFrame(uint32 output_surface_id, 201 int host_process_id, 202 int host_routing_id, 203 scoped_ptr<cc::CompositorFrame> frame); 204 205 void SetContentsOpaque(bool opaque); 206 207 private: 208 class EmbedderWebContentsObserver; 209 210 // BrowserPluginGuest is a WebContentsObserver of |web_contents| and 211 // |web_contents| has to stay valid for the lifetime of BrowserPluginGuest. 212 BrowserPluginGuest(bool has_render_view, 213 WebContentsImpl* web_contents, 214 BrowserPluginGuestDelegate* delegate); 215 216 void WillDestroy(); 217 218 void Initialize(int browser_plugin_instance_id, 219 const BrowserPluginHostMsg_Attach_Params& params, 220 WebContentsImpl* embedder_web_contents); 221 222 bool InAutoSizeBounds(const gfx::Size& size) const; 223 224 // Message handlers for messages from embedder. 225 226 void OnCompositorFrameSwappedACK( 227 int instance_id, 228 const FrameHostMsg_CompositorFrameSwappedACK_Params& params); 229 void OnCopyFromCompositingSurfaceAck(int instance_id, 230 int request_id, 231 const SkBitmap& bitmap); 232 // Handles drag events from the embedder. 233 // When dragging, the drag events go to the embedder first, and if the drag 234 // happens on the browser plugin, then the plugin sends a corresponding 235 // drag-message to the guest. This routes the drag-message to the guest 236 // renderer. 237 void OnDragStatusUpdate(int instance_id, 238 blink::WebDragStatus drag_status, 239 const DropData& drop_data, 240 blink::WebDragOperationsMask drag_mask, 241 const gfx::Point& location); 242 // Instructs the guest to execute an edit command decoded in the embedder. 243 void OnExecuteEditCommand(int instance_id, 244 const std::string& command); 245 246 // Returns compositor resources reclaimed in the embedder to the guest. 247 void OnReclaimCompositorResources( 248 int instance_id, 249 const FrameHostMsg_ReclaimCompositorResources_Params& params); 250 251 void OnLockMouse(bool user_gesture, 252 bool last_unlocked_by_target, 253 bool privileged); 254 void OnLockMouseAck(int instance_id, bool succeeded); 255 void OnPluginDestroyed(int instance_id); 256 // Resizes the guest's web contents. 257 void OnResizeGuest( 258 int instance_id, const BrowserPluginHostMsg_ResizeGuest_Params& params); 259 void OnSetFocus(int instance_id, bool focused); 260 // Sets the name of the guest so that other guests in the same partition can 261 // access it. 262 void OnSetName(int instance_id, const std::string& name); 263 // Updates the size state of the guest. 264 void OnSetEditCommandsForNextKeyEvent( 265 int instance_id, 266 const std::vector<EditCommand>& edit_commands); 267 // The guest WebContents is visible if both its embedder is visible and 268 // the browser plugin element is visible. If either one is not then the 269 // WebContents is marked as hidden. A hidden WebContents will consume 270 // fewer GPU and CPU resources. 271 // 272 // When every WebContents in a RenderProcessHost is hidden, it will lower 273 // the priority of the process (see RenderProcessHostImpl::WidgetHidden). 274 // 275 // It will also send a message to the guest renderer process to cleanup 276 // resources such as dropping back buffers and adjusting memory limits (if in 277 // compositing mode, see CCLayerTreeHost::setVisible). 278 // 279 // Additionally, it will slow down Javascript execution and garbage 280 // collection. See RenderThreadImpl::IdleHandler (executed when hidden) and 281 // RenderThreadImpl::IdleHandlerInForegroundTab (executed when visible). 282 void OnSetVisibility(int instance_id, bool visible); 283 void OnUnlockMouse(); 284 void OnUnlockMouseAck(int instance_id); 285 void OnUpdateGeometry(int instance_id, const gfx::Rect& view_rect); 286 287 void OnTextInputTypeChanged(ui::TextInputType type, 288 ui::TextInputMode input_mode, 289 bool can_compose_inline); 290 void OnImeSetComposition( 291 int instance_id, 292 const std::string& text, 293 const std::vector<blink::WebCompositionUnderline>& underlines, 294 int selection_start, 295 int selection_end); 296 void OnImeConfirmComposition( 297 int instance_id, 298 const std::string& text, 299 bool keep_selection); 300 void OnExtendSelectionAndDelete(int instance_id, int before, int after); 301 void OnImeCancelComposition(); 302 #if defined(OS_MACOSX) || defined(USE_AURA) 303 void OnImeCompositionRangeChanged( 304 const gfx::Range& range, 305 const std::vector<gfx::Rect>& character_bounds); 306 #endif 307 308 // Message handlers for messages from guest. 309 void OnHandleInputEventAck( 310 blink::WebInputEvent::Type event_type, 311 InputEventAckState ack_result); 312 void OnHasTouchEventHandlers(bool accept); 313 #if defined(OS_MACOSX) 314 // On MacOS X popups are painted by the browser process. We handle them here 315 // so that they are positioned correctly. 316 void OnShowPopup(RenderFrameHost* render_frame_host, 317 const FrameHostMsg_ShowPopup_Params& params); 318 #endif 319 void OnShowWidget(int route_id, const gfx::Rect& initial_pos); 320 void OnTakeFocus(bool reverse); 321 void OnUpdateFrameName(int frame_id, 322 bool is_top_level, 323 const std::string& name); 324 325 // Forwards all messages from the |pending_messages_| queue to the embedder. 326 void SendQueuedMessages(); 327 328 scoped_ptr<EmbedderWebContentsObserver> embedder_web_contents_observer_; 329 WebContentsImpl* embedder_web_contents_; 330 331 // An identifier that uniquely identifies a browser plugin within an embedder. 332 int browser_plugin_instance_id_; 333 float guest_device_scale_factor_; 334 gfx::Rect guest_window_rect_; 335 bool focused_; 336 bool mouse_locked_; 337 bool pending_lock_request_; 338 bool guest_visible_; 339 bool embedder_visible_; 340 341 // Each copy-request is identified by a unique number. The unique number is 342 // used to keep track of the right callback. 343 int copy_request_id_; 344 typedef base::Callback<void(bool, const SkBitmap&)> CopyRequestCallback; 345 typedef std::map<int, const CopyRequestCallback> CopyRequestMap; 346 CopyRequestMap copy_request_callbacks_; 347 348 // Indicates that this BrowserPluginGuest has associated renderer-side state. 349 // This is used to determine whether or not to create a new RenderView when 350 // this guest is attached. A BrowserPluginGuest would have renderer-side state 351 // prior to attachment if it is created via a call to window.open and 352 // maintains a JavaScript reference to its opener. 353 bool has_render_view_; 354 355 // Last seen size of guest contents (by SwapCompositorFrame). 356 gfx::Size last_seen_view_size_; 357 // Last seen size of BrowserPlugin (by OnResizeGuest). 358 gfx::Size last_seen_browser_plugin_size_; 359 360 bool is_in_destruction_; 361 362 // Text input type states. 363 ui::TextInputType last_text_input_type_; 364 ui::TextInputMode last_input_mode_; 365 bool last_can_compose_inline_; 366 367 // This is a queue of messages that are destined to be sent to the embedder 368 // once the guest is attached to a particular embedder. 369 std::deque<linked_ptr<IPC::Message> > pending_messages_; 370 371 BrowserPluginGuestDelegate* const delegate_; 372 373 // Weak pointer used to ask GeolocationPermissionContext about geolocation 374 // permission. 375 base::WeakPtrFactory<BrowserPluginGuest> weak_ptr_factory_; 376 377 DISALLOW_COPY_AND_ASSIGN(BrowserPluginGuest); 378 }; 379 380 } // namespace content 381 382 #endif // CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_H_ 383