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