|  | // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | // A BrowserPluginGuest is the browser side of a browser <--> embedder | 
|  | // renderer channel. A BrowserPlugin (a WebPlugin) is on the embedder | 
|  | // renderer side of browser <--> embedder renderer communication. | 
|  | // | 
|  | // BrowserPluginGuest lives on the UI thread of the browser process. Any | 
|  | // messages about the guest render process that the embedder might be interested | 
|  | // in receiving should be listened for here. | 
|  | // | 
|  | // BrowserPluginGuest is a WebContentsObserver for the guest WebContents. | 
|  | // BrowserPluginGuest operates under the assumption that the guest will be | 
|  | // accessible through only one RenderViewHost for the lifetime of | 
|  | // the guest WebContents. Thus, cross-process navigation is not supported. | 
|  |  | 
|  | #ifndef CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_H_ | 
|  | #define CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_H_ | 
|  |  | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include <map> | 
|  | #include <memory> | 
|  | #include <queue> | 
|  |  | 
|  | #include "base/compiler_specific.h" | 
|  | #include "base/macros.h" | 
|  | #include "base/memory/weak_ptr.h" | 
|  | #include "base/values.h" | 
|  | #include "build/build_config.h" | 
|  | #include "content/common/edit_command.h" | 
|  | #include "content/common/input/input_event_ack_state.h" | 
|  | #include "content/public/browser/browser_plugin_guest_delegate.h" | 
|  | #include "content/public/browser/guest_host.h" | 
|  | #include "content/public/browser/readback_types.h" | 
|  | #include "content/public/browser/web_contents_observer.h" | 
|  | #include "third_party/WebKit/public/platform/WebDragOperation.h" | 
|  | #include "third_party/WebKit/public/platform/WebFocusType.h" | 
|  | #include "third_party/WebKit/public/platform/WebInputEvent.h" | 
|  | #include "third_party/WebKit/public/web/WebDragStatus.h" | 
|  | #include "third_party/WebKit/public/web/WebImeTextSpan.h" | 
|  | #include "ui/base/ime/text_input_mode.h" | 
|  | #include "ui/base/ime/text_input_type.h" | 
|  | #include "ui/gfx/geometry/rect.h" | 
|  |  | 
|  | struct BrowserPluginHostMsg_Attach_Params; | 
|  | struct BrowserPluginHostMsg_SetComposition_Params; | 
|  |  | 
|  | #if defined(OS_MACOSX) | 
|  | struct FrameHostMsg_ShowPopup_Params; | 
|  | #endif | 
|  |  | 
|  | namespace gfx { | 
|  | class Range; | 
|  | }  // namespace gfx | 
|  |  | 
|  | namespace viz { | 
|  | class SurfaceId; | 
|  | class SurfaceInfo; | 
|  | struct SurfaceSequence; | 
|  | }  // namespace viz | 
|  |  | 
|  | namespace content { | 
|  |  | 
|  | class BrowserPluginGuestManager; | 
|  | class RenderViewHostImpl; | 
|  | class RenderWidgetHost; | 
|  | class RenderWidgetHostImpl; | 
|  | class RenderWidgetHostView; | 
|  | class RenderWidgetHostViewBase; | 
|  | class SiteInstance; | 
|  | struct DropData; | 
|  | struct TextInputState; | 
|  |  | 
|  | // A browser plugin guest provides functionality for WebContents to operate in | 
|  | // the guest role and implements guest-specific overrides for ViewHostMsg_* | 
|  | // messages. | 
|  | // | 
|  | // When a guest is initially created, it is in an unattached state. That is, | 
|  | // it is not visible anywhere and has no embedder WebContents assigned. | 
|  | // A BrowserPluginGuest is said to be "attached" if it has an embedder. | 
|  | // A BrowserPluginGuest can also create a new unattached guest via | 
|  | // CreateNewWindow. The newly created guest will live in the same partition, | 
|  | // which means it can share storage and can script this guest. | 
|  | // | 
|  | // Note: in --site-per-process, all IPCs sent out from this class will be | 
|  | // dropped on the floor since we don't have a BrowserPlugin. | 
|  | class CONTENT_EXPORT BrowserPluginGuest : public GuestHost, | 
|  | public WebContentsObserver { | 
|  | public: | 
|  | ~BrowserPluginGuest() override; | 
|  |  | 
|  | // The WebContents passed into the factory method here has not been | 
|  | // initialized yet and so it does not yet hold a SiteInstance. | 
|  | // BrowserPluginGuest must be constructed and installed into a WebContents | 
|  | // prior to its initialization because WebContents needs to determine what | 
|  | // type of WebContentsView to construct on initialization. The content | 
|  | // embedder needs to be aware of |guest_site_instance| on the guest's | 
|  | // construction and so we pass it in here. | 
|  | static BrowserPluginGuest* Create(WebContentsImpl* web_contents, | 
|  | BrowserPluginGuestDelegate* delegate); | 
|  |  | 
|  | // Returns whether the given WebContents is a BrowserPlugin guest. | 
|  | static bool IsGuest(WebContentsImpl* web_contents); | 
|  |  | 
|  | // Returns whether the given RenderviewHost is a BrowserPlugin guest. | 
|  | static bool IsGuest(RenderViewHostImpl* render_view_host); | 
|  |  | 
|  | // BrowserPluginGuest::Init is called after the associated guest WebContents | 
|  | // initializes. If this guest cannot navigate without being attached to a | 
|  | // container, then this call is a no-op. For guest types that can be | 
|  | // navigated, this call adds the associated RenderWdigetHostViewGuest to the | 
|  | // view hierachy and sets up the appropriate RendererPreferences so that this | 
|  | // guest can navigate and resize offscreen. | 
|  | void Init(); | 
|  |  | 
|  | // Returns a WeakPtr to this BrowserPluginGuest. | 
|  | base::WeakPtr<BrowserPluginGuest> AsWeakPtr(); | 
|  |  | 
|  | // Sets the focus state of the current RenderWidgetHostView. | 
|  | void SetFocus(RenderWidgetHost* rwh, | 
|  | bool focused, | 
|  | blink::WebFocusType focus_type); | 
|  |  | 
|  | // Sets the tooltip text. | 
|  | void SetTooltipText(const base::string16& tooltip_text); | 
|  |  | 
|  | // Sets the lock state of the pointer. Returns true if |allowed| is true and | 
|  | // the mouse has been successfully locked. | 
|  | bool LockMouse(bool allowed); | 
|  |  | 
|  | // Return true if the mouse is locked. | 
|  | bool mouse_locked() const { return mouse_locked_; } | 
|  |  | 
|  | // Called when the embedder WebContents changes visibility. | 
|  | void EmbedderVisibilityChanged(bool visible); | 
|  |  | 
|  | // Creates a new guest WebContentsImpl with the provided |params| with |this| | 
|  | // as the |opener|. | 
|  | WebContentsImpl* CreateNewGuestWindow( | 
|  | const WebContents::CreateParams& params); | 
|  |  | 
|  | // Creates, if necessary, and returns the routing ID of a proxy for the guest | 
|  | // in the owner's renderer process. | 
|  | int GetGuestProxyRoutingID(); | 
|  |  | 
|  | // Returns the identifier that uniquely identifies a browser plugin guest | 
|  | // within an embedder. | 
|  | int browser_plugin_instance_id() const { return browser_plugin_instance_id_; } | 
|  |  | 
|  | bool OnMessageReceivedFromEmbedder(const IPC::Message& message); | 
|  |  | 
|  | WebContentsImpl* embedder_web_contents() const { | 
|  | return attached_ ? owner_web_contents_ : nullptr; | 
|  | } | 
|  |  | 
|  | // Returns the embedder's RenderWidgetHostView if it is available. | 
|  | // Returns nullptr otherwise. | 
|  | RenderWidgetHostView* GetOwnerRenderWidgetHostView(); | 
|  |  | 
|  | bool focused() const { return focused_; } | 
|  | bool visible() const { return guest_visible_; } | 
|  | bool is_in_destruction() { return is_in_destruction_; } | 
|  |  | 
|  | void UpdateVisibility(); | 
|  |  | 
|  | BrowserPluginGuestManager* GetBrowserPluginGuestManager() const; | 
|  |  | 
|  | // WebContentsObserver implementation. | 
|  | void DidFinishNavigation(NavigationHandle* navigation_handle) override; | 
|  |  | 
|  | void RenderViewReady() override; | 
|  | void RenderProcessGone(base::TerminationStatus status) override; | 
|  | bool OnMessageReceived(const IPC::Message& message) override; | 
|  | bool OnMessageReceived(const IPC::Message& message, | 
|  | RenderFrameHost* render_frame_host) override; | 
|  |  | 
|  | // GuestHost implementation. | 
|  | int LoadURLWithParams( | 
|  | const NavigationController::LoadURLParams& load_params) override; | 
|  | void GuestResizeDueToAutoResize(const gfx::Size& new_size) override; | 
|  | void SizeContents(const gfx::Size& new_size) override; | 
|  | void WillDestroy() override; | 
|  |  | 
|  | // Exposes the protected web_contents() from WebContentsObserver. | 
|  | WebContentsImpl* GetWebContents() const; | 
|  |  | 
|  | gfx::Point GetScreenCoordinates(const gfx::Point& relative_position) const; | 
|  |  | 
|  | // This method is called by the RenderWidgetHostViewGuest to inform the | 
|  | // BrowserPlugin of the potential location of the context menu event (to | 
|  | // come). The need for this (hack) is that the input events when passed on to | 
|  | // the BrowserPlugin are modified by any CSS transforms applied on the plugin. | 
|  | // Therefore, the coordinates of the context menu event with respect to the | 
|  | // container window are modifed with the guest renderer process beiung unaware | 
|  | // of the change. Then eventually, when the context menu event arrives at the | 
|  | // browser, it contains the wrong coordinates (BUG=470087). | 
|  | // TODO(ekaramad): Find a more fundamental solution and remove this later. | 
|  | void SetContextMenuPosition(const gfx::Point& position); | 
|  |  | 
|  | // Helper to send messages to embedder. If this guest is not yet attached, | 
|  | // then IPCs will be queued until attachment. | 
|  | void SendMessageToEmbedder(std::unique_ptr<IPC::Message> msg); | 
|  |  | 
|  | // Returns whether the guest is attached to an embedder. | 
|  | bool attached() const { return attached_; } | 
|  |  | 
|  | // Returns true when an attachment has taken place since the last time the | 
|  | // compositor surface was set. | 
|  | bool has_attached_since_surface_set() const { | 
|  | return has_attached_since_surface_set_; | 
|  | } | 
|  |  | 
|  | // Attaches this BrowserPluginGuest to the provided |embedder_web_contents| | 
|  | // and initializes the guest with the provided |params|. Attaching a guest | 
|  | // to an embedder implies that this guest's lifetime is no longer managed | 
|  | // by its opener, and it can begin loading resources. | 
|  | void Attach(int browser_plugin_instance_id, | 
|  | WebContentsImpl* embedder_web_contents, | 
|  | const BrowserPluginHostMsg_Attach_Params& params); | 
|  |  | 
|  | // Returns whether BrowserPluginGuest is interested in receiving the given | 
|  | // |message|. | 
|  | static bool ShouldForwardToBrowserPluginGuest(const IPC::Message& message); | 
|  |  | 
|  | void DragSourceEndedAt(int client_x, int client_y, int screen_x, | 
|  | int screen_y, blink::WebDragOperation operation); | 
|  |  | 
|  | // Called when the drag started by this guest ends at an OS-level. | 
|  | void EmbedderSystemDragEnded(); | 
|  | void EndSystemDragIfApplicable(); | 
|  |  | 
|  | void RespondToPermissionRequest(int request_id, | 
|  | bool should_allow, | 
|  | const std::string& user_input); | 
|  |  | 
|  | void PointerLockPermissionResponse(bool allow); | 
|  |  | 
|  | // The next function is virtual for test purposes. | 
|  | virtual void SetChildFrameSurface(const viz::SurfaceInfo& surface_info, | 
|  | const viz::SurfaceSequence& sequence); | 
|  |  | 
|  | void ResendEventToEmbedder(const blink::WebInputEvent& event); | 
|  |  | 
|  | // TODO(ekaramad): Remove this once https://crbug.com/642826 is resolved. | 
|  | bool can_use_cross_process_frames() const { | 
|  | return can_use_cross_process_frames_; | 
|  | } | 
|  |  | 
|  | gfx::Point GetCoordinatesInEmbedderWebContents( | 
|  | const gfx::Point& relative_point); | 
|  |  | 
|  | protected: | 
|  |  | 
|  | // BrowserPluginGuest is a WebContentsObserver of |web_contents| and | 
|  | // |web_contents| has to stay valid for the lifetime of BrowserPluginGuest. | 
|  | // Constructor protected for testing. | 
|  | BrowserPluginGuest(bool has_render_view, | 
|  | WebContentsImpl* web_contents, | 
|  | BrowserPluginGuestDelegate* delegate); | 
|  |  | 
|  | // Protected for testing. | 
|  | void set_has_attached_since_surface_set_for_test(bool has_attached) { | 
|  | has_attached_since_surface_set_ = has_attached; | 
|  | } | 
|  |  | 
|  | void set_attached_for_test(bool attached) { | 
|  | attached_ = attached; | 
|  | } | 
|  |  | 
|  | private: | 
|  | class EmbedderVisibilityObserver; | 
|  |  | 
|  | // The RenderWidgetHostImpl corresponding to the owner frame of BrowserPlugin. | 
|  | RenderWidgetHostImpl* GetOwnerRenderWidgetHost() const; | 
|  |  | 
|  | void InitInternal(const BrowserPluginHostMsg_Attach_Params& params, | 
|  | WebContentsImpl* owner_web_contents); | 
|  |  | 
|  | void OnSatisfySequence(int instance_id, const viz::SurfaceSequence& sequence); | 
|  | void OnRequireSequence(int instance_id, | 
|  | const viz::SurfaceId& id, | 
|  | const viz::SurfaceSequence& sequence); | 
|  | // Message handlers for messages from embedder. | 
|  | void OnDetach(int instance_id); | 
|  | // Handles drag events from the embedder. | 
|  | // When dragging, the drag events go to the embedder first, and if the drag | 
|  | // happens on the browser plugin, then the plugin sends a corresponding | 
|  | // drag-message to the guest. This routes the drag-message to the guest | 
|  | // renderer. | 
|  | void OnDragStatusUpdate(int instance_id, | 
|  | blink::WebDragStatus drag_status, | 
|  | const DropData& drop_data, | 
|  | blink::WebDragOperationsMask drag_mask, | 
|  | const gfx::Point& location); | 
|  | // Instructs the guest to execute an edit command decoded in the embedder. | 
|  | void OnExecuteEditCommand(int instance_id, | 
|  | const std::string& command); | 
|  |  | 
|  | void OnLockMouse(bool user_gesture, | 
|  | bool privileged); | 
|  | void OnLockMouseAck(int instance_id, bool succeeded); | 
|  | // Resizes the guest's web contents. | 
|  | void OnSetFocus(int instance_id, | 
|  | bool focused, | 
|  | blink::WebFocusType focus_type); | 
|  | // Sets the name of the guest so that other guests in the same partition can | 
|  | // access it. | 
|  | void OnSetName(int instance_id, const std::string& name); | 
|  | // Updates the size state of the guest. | 
|  | void OnSetEditCommandsForNextKeyEvent( | 
|  | int instance_id, | 
|  | const std::vector<EditCommand>& edit_commands); | 
|  | // The guest WebContents is visible if both its embedder is visible and | 
|  | // the browser plugin element is visible. If either one is not then the | 
|  | // WebContents is marked as hidden. A hidden WebContents will consume | 
|  | // fewer GPU and CPU resources. | 
|  | // | 
|  | // When every WebContents in a RenderProcessHost is hidden, it will lower | 
|  | // the priority of the process (see RenderProcessHostImpl::WidgetHidden). | 
|  | // | 
|  | // It will also send a message to the guest renderer process to cleanup | 
|  | // resources such as dropping back buffers and adjusting memory limits (if in | 
|  | // compositing mode, see CCLayerTreeHost::setVisible). | 
|  | // | 
|  | // Additionally, it will slow down Javascript execution and garbage | 
|  | // collection. See RenderThreadImpl::IdleHandler (executed when hidden) and | 
|  | // RenderThreadImpl::IdleHandlerInForegroundTab (executed when visible). | 
|  | void OnSetVisibility(int instance_id, bool visible); | 
|  | void OnUnlockMouse(); | 
|  | void OnUnlockMouseAck(int instance_id); | 
|  | void OnUpdateGeometry(int instance_id, const gfx::Rect& view_rect); | 
|  |  | 
|  | void OnTextInputStateChanged(const TextInputState& params); | 
|  | void OnImeSetComposition( | 
|  | int instance_id, | 
|  | const BrowserPluginHostMsg_SetComposition_Params& params); | 
|  | void OnImeCommitText(int instance_id, | 
|  | const base::string16& text, | 
|  | const std::vector<blink::WebImeTextSpan>& ime_text_spans, | 
|  | const gfx::Range& replacement_range, | 
|  | int relative_cursor_pos); | 
|  | void OnImeFinishComposingText(int instance_id, bool keep_selection); | 
|  | void OnExtendSelectionAndDelete(int instance_id, int before, int after); | 
|  | void OnImeCancelComposition(); | 
|  | #if defined(OS_MACOSX) || defined(USE_AURA) | 
|  | void OnImeCompositionRangeChanged( | 
|  | const gfx::Range& range, | 
|  | const std::vector<gfx::Rect>& character_bounds); | 
|  | #endif | 
|  |  | 
|  | // Message handlers for messages from guest. | 
|  | void OnHandleInputEventAck( | 
|  | blink::WebInputEvent::Type event_type, | 
|  | InputEventAckState ack_result); | 
|  | void OnHasTouchEventHandlers(bool accept); | 
|  | #if defined(OS_MACOSX) | 
|  | // On MacOS X popups are painted by the browser process. We handle them here | 
|  | // so that they are positioned correctly. | 
|  | void OnShowPopup(RenderFrameHost* render_frame_host, | 
|  | const FrameHostMsg_ShowPopup_Params& params); | 
|  | #endif | 
|  | void OnShowWidget(int route_id, const gfx::Rect& initial_rect); | 
|  | void OnTakeFocus(bool reverse); | 
|  | void OnUpdateFrameName(int frame_id, | 
|  | bool is_top_level, | 
|  | const std::string& name); | 
|  |  | 
|  | // Called when WillAttach is complete. | 
|  | void OnWillAttachComplete(WebContentsImpl* embedder_web_contents, | 
|  | const BrowserPluginHostMsg_Attach_Params& params); | 
|  |  | 
|  | // Returns identical message with current browser_plugin_instance_id() if | 
|  | // the input was created with browser_plugin::kInstanceIdNone, else it returns | 
|  | // the input message unmodified. If no current browser_plugin_instance_id() | 
|  | // is set, or anything goes wrong, the input message is returned. | 
|  | std::unique_ptr<IPC::Message> UpdateInstanceIdIfNecessary( | 
|  | std::unique_ptr<IPC::Message> msg) const; | 
|  |  | 
|  | // Forwards all messages from the |pending_messages_| queue to the embedder. | 
|  | void SendQueuedMessages(); | 
|  |  | 
|  | void SendTextInputTypeChangedToView(RenderWidgetHostViewBase* guest_rwhv); | 
|  |  | 
|  | // The last tooltip that was set with SetTooltipText(). | 
|  | base::string16 current_tooltip_text_; | 
|  |  | 
|  | std::unique_ptr<EmbedderVisibilityObserver> embedder_visibility_observer_; | 
|  | WebContentsImpl* owner_web_contents_; | 
|  |  | 
|  | // Indicates whether this guest has been attached to a container. | 
|  | bool attached_; | 
|  |  | 
|  | // Used to signal if a browser plugin has been attached since the last time | 
|  | // the compositing surface was set. | 
|  | bool has_attached_since_surface_set_; | 
|  |  | 
|  | // An identifier that uniquely identifies a browser plugin within an embedder. | 
|  | int browser_plugin_instance_id_; | 
|  | gfx::Rect guest_window_rect_; | 
|  | bool focused_; | 
|  | bool mouse_locked_; | 
|  | bool pending_lock_request_; | 
|  | bool guest_visible_; | 
|  | bool embedder_visible_; | 
|  | // Whether the browser plugin is inside a plugin document. | 
|  | bool is_full_page_plugin_; | 
|  |  | 
|  | // Indicates that this BrowserPluginGuest has associated renderer-side state. | 
|  | // This is used to determine whether or not to create a new RenderView when | 
|  | // this guest is attached. A BrowserPluginGuest would have renderer-side state | 
|  | // prior to attachment if it is created via a call to window.open and | 
|  | // maintains a JavaScript reference to its opener. | 
|  | bool has_render_view_; | 
|  |  | 
|  | // Last seen size of guest contents (by SwapCompositorFrame). | 
|  | gfx::Size last_seen_view_size_; | 
|  |  | 
|  | bool is_in_destruction_; | 
|  |  | 
|  | // BrowserPluginGuest::Init can only be called once. This flag allows it to | 
|  | // exit early if it's already been called. | 
|  | bool initialized_; | 
|  |  | 
|  | // Text input type states. | 
|  | // Using scoped_ptr to avoid including the header file: view_messages.h. | 
|  | std::unique_ptr<const TextInputState> last_text_input_state_; | 
|  |  | 
|  | // The is the routing ID for a swapped out RenderView for the guest | 
|  | // WebContents in the embedder's process. | 
|  | int guest_proxy_routing_id_; | 
|  | // Last seen state of drag status update. | 
|  | blink::WebDragStatus last_drag_status_; | 
|  | // Whether or not our embedder has seen a SystemDragEnded() call. | 
|  | bool seen_embedder_system_drag_ended_; | 
|  | // Whether or not our embedder has seen a DragSourceEndedAt() call. | 
|  | bool seen_embedder_drag_source_ended_at_; | 
|  |  | 
|  | // Ignore the URL dragged into guest that is coming from guest. | 
|  | bool ignore_dragged_url_; | 
|  |  | 
|  | // This is a queue of messages that are destined to be sent to the embedder | 
|  | // once the guest is attached to a particular embedder. | 
|  | std::deque<std::unique_ptr<IPC::Message>> pending_messages_; | 
|  |  | 
|  | BrowserPluginGuestDelegate* const delegate_; | 
|  |  | 
|  | // Whether or not this BrowserPluginGuest can use cross process frames. This | 
|  | // means when we have --use-cross-process-frames-for-guests on, the | 
|  | // WebContents associated with this BrowserPluginGuest has OOPIF structure. | 
|  | bool can_use_cross_process_frames_; | 
|  |  | 
|  | // Weak pointer used to ask GeolocationPermissionContext about geolocation | 
|  | // permission. | 
|  | base::WeakPtrFactory<BrowserPluginGuest> weak_ptr_factory_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(BrowserPluginGuest); | 
|  | }; | 
|  |  | 
|  | }  // namespace content | 
|  |  | 
|  | #endif  // CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_GUEST_H_ |