// 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.

#include "content/browser/browser_plugin/browser_plugin_guest.h"

#include <stddef.h>

#include <algorithm>
#include <memory>
#include <string>
#include <utility>

#include "base/macros.h"
#include "base/metrics/user_metrics.h"
#include "base/pickle.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "components/viz/common/features.h"
#include "components/viz/common/surfaces/surface_info.h"
#include "components/viz/service/surfaces/surface.h"
#include "content/browser/browser_plugin/browser_plugin_embedder.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/frame_host/render_frame_proxy_host.h"
#include "content/browser/frame_host/render_widget_host_view_guest.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/renderer_host/cursor_manager.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_contents/web_contents_view_guest.h"
#include "content/common/browser_plugin/browser_plugin_constants.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/content_constants_internal.h"
#include "content/common/drag_messages.h"
#include "content/common/frame_visual_properties.h"
#include "content/common/input/ime_text_span_conversions.h"
#include "content/common/text_input_state.h"
#include "content/common/view_messages.h"
#include "content/common/widget_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_plugin_guest_manager.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/guest_host.h"
#include "content/public/browser/guest_mode.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/drop_data.h"
#include "ui/base/ui_base_features.h"
#include "ui/events/blink/web_input_event_traits.h"
#include "ui/gfx/geometry/size_conversions.h"

#if defined(OS_MACOSX)
#include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h"
#include "content/common/frame_messages.h"
#endif

namespace content {

BrowserPluginGuest::InputEventShimImpl::InputEventShimImpl(
    BrowserPluginGuest* browser_plugin_guest)
    : browser_plugin_guest_(browser_plugin_guest) {}

BrowserPluginGuest::InputEventShimImpl::~InputEventShimImpl() = default;

void BrowserPluginGuest::InputEventShimImpl::DidSetHasTouchEventHandlers(
    bool accept) {
  browser_plugin_guest_->DidSetHasTouchEventHandlers(accept);
}

void BrowserPluginGuest::InputEventShimImpl::DidTextInputStateChange(
    const TextInputState& params) {
  browser_plugin_guest_->DidTextInputStateChange(params);
}

void BrowserPluginGuest::InputEventShimImpl::DidLockMouse(bool user_gesture,
                                                          bool privileged) {
  browser_plugin_guest_->DidLockMouse(user_gesture, privileged);
}

void BrowserPluginGuest::InputEventShimImpl::DidUnlockMouse() {
  browser_plugin_guest_->DidUnlockMouse();
}

class BrowserPluginGuest::EmbedderVisibilityObserver
    : public WebContentsObserver {
 public:
  explicit EmbedderVisibilityObserver(BrowserPluginGuest* guest)
      : WebContentsObserver(guest->embedder_web_contents()),
        browser_plugin_guest_(guest) {
  }

  ~EmbedderVisibilityObserver() override {}

  // WebContentsObserver implementation.
  void OnVisibilityChanged(content::Visibility visibility) override {
    browser_plugin_guest_->EmbedderVisibilityChanged(visibility);
  }

 private:
  BrowserPluginGuest* browser_plugin_guest_;

  DISALLOW_COPY_AND_ASSIGN(EmbedderVisibilityObserver);
};

BrowserPluginGuest::BrowserPluginGuest(bool has_render_view,
                                       WebContentsImpl* web_contents,
                                       BrowserPluginGuestDelegate* delegate)
    : WebContentsObserver(web_contents),
      input_event_shim_impl_(this),
      owner_web_contents_(nullptr),
      attached_(false),
      browser_plugin_instance_id_(browser_plugin::kInstanceIDNone),
      focused_(false),
      mouse_locked_(false),
      pending_lock_request_(false),
      guest_visible_(false),
      embedder_visibility_(Visibility::VISIBLE),
      is_full_page_plugin_(false),
      has_render_view_(has_render_view),
      is_in_destruction_(false),
      initialized_(false),
      guest_proxy_routing_id_(MSG_ROUTING_NONE),
      last_drag_status_(blink::kWebDragStatusUnknown),
      seen_embedder_system_drag_ended_(false),
      seen_embedder_drag_source_ended_at_(false),
      ignore_dragged_url_(true),
      delegate_(delegate),
      can_use_cross_process_frames_(delegate->CanUseCrossProcessFrames()),
      weak_ptr_factory_(this) {
  DCHECK(web_contents);
  DCHECK(delegate);
  RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Create"));
}

int BrowserPluginGuest::GetGuestProxyRoutingID() {
  if (GuestMode::IsCrossProcessFrameGuest(GetWebContents())) {
    // We don't use the proxy to send postMessage in --site-per-process, since
    // we use the contentWindow directly from the frame element instead.
    return MSG_ROUTING_NONE;
  }

  if (guest_proxy_routing_id_ != MSG_ROUTING_NONE)
    return guest_proxy_routing_id_;

  // In order to enable the embedder to post messages to the
  // guest, we need to create a RenderFrameProxyHost in root node of guest
  // WebContents' frame tree (i.e., create a RenderFrameProxy in the embedder
  // process which can be used by the embedder to post messages to the guest).
  // The creation of RFPH for the reverse path, which enables the guest to post
  // messages to the embedder, will be postponed to when the embedder posts its
  // first message to the guest.
  //
  // TODO(fsamuel): Make sure this works for transferring guests across
  // owners in different processes. We probably need to clear the
  // |guest_proxy_routing_id_| and perform any necessary cleanup on Detach
  // to enable this.
  //
  // TODO(ekaramad): If the guest is embedded inside a cross-process <iframe>
  // (e.g., <embed>-ed PDF), the reverse proxy will not be created and the
  // posted message's source attribute will be null which in turn breaks the
  // two-way messaging between the guest and the embedder. We should either
  // create a RenderFrameProxyHost for the reverse path, or implement
  // MimeHandlerViewGuest using OOPIF (https://crbug.com/659750).
  SiteInstance* owner_site_instance = delegate_->GetOwnerSiteInstance();
  if (!owner_site_instance)
    return MSG_ROUTING_NONE;
  int proxy_routing_id = GetWebContents()
                             ->GetFrameTree()
                             ->root()
                             ->render_manager()
                             ->CreateRenderFrameProxy(owner_site_instance);
  guest_proxy_routing_id_ = RenderFrameProxyHost::FromID(
      owner_site_instance->GetProcess()->GetID(), proxy_routing_id)
          ->GetRenderViewHost()->GetRoutingID();

  return guest_proxy_routing_id_;
}

int BrowserPluginGuest::LoadURLWithParams(
    const NavigationController::LoadURLParams& load_params) {
  GetWebContents()->GetController().LoadURLWithParams(load_params);
  return GetGuestProxyRoutingID();
}

void BrowserPluginGuest::EnableAutoResize(const gfx::Size& min_size,
                                          const gfx::Size& max_size) {
  SendMessageToEmbedder(std::make_unique<BrowserPluginMsg_EnableAutoResize>(
      browser_plugin_instance_id_, min_size, max_size));
}

void BrowserPluginGuest::DisableAutoResize() {
  SendMessageToEmbedder(std::make_unique<BrowserPluginMsg_DisableAutoResize>(
      browser_plugin_instance_id_));
}

void BrowserPluginGuest::DidUpdateVisualProperties(
    const cc::RenderFrameMetadata& metadata) {
  SendMessageToEmbedder(
      std::make_unique<BrowserPluginMsg_DidUpdateVisualProperties>(
          browser_plugin_instance_id_, metadata));
}

void BrowserPluginGuest::SizeContents(const gfx::Size& new_size) {
  GetWebContents()->GetView()->SizeContents(new_size);
}

void BrowserPluginGuest::WillDestroy() {
  is_in_destruction_ = true;

  // It is important that the WebContents is notified before detaching.
  GetWebContents()->BrowserPluginGuestWillDetach();

  attached_ = false;
  owner_web_contents_ = nullptr;
}

RenderWidgetHostImpl* BrowserPluginGuest::GetOwnerRenderWidgetHost() const {
  return static_cast<RenderWidgetHostImpl*>(
      delegate_->GetOwnerRenderWidgetHost());
}

void BrowserPluginGuest::Init() {
  if (initialized_)
    return;
  initialized_ = true;

  WebContentsImpl* owner_web_contents = static_cast<WebContentsImpl*>(
      delegate_->GetOwnerWebContents());
  owner_web_contents->CreateBrowserPluginEmbedderIfNecessary();
  InitInternal(BrowserPluginHostMsg_Attach_Params(), owner_web_contents);
}

InputEventShim* BrowserPluginGuest::GetInputEventShim() {
  // In --site-per-process mode, the input event mechanics are handled by
  // the RenderWidgetHost so there is no need to shim things.
  if (GuestMode::IsCrossProcessFrameGuest(GetWebContents())) {
    return nullptr;
  }
  return &input_event_shim_impl_;
}

base::WeakPtr<BrowserPluginGuest> BrowserPluginGuest::AsWeakPtr() {
  return weak_ptr_factory_.GetWeakPtr();
}

void BrowserPluginGuest::SetFocus(RenderWidgetHost* rwh,
                                  bool focused,
                                  blink::WebFocusType focus_type) {
  focused_ = focused;
  if (!rwh)
    return;

  if ((focus_type == blink::kWebFocusTypeForward) ||
      (focus_type == blink::kWebFocusTypeBackward)) {
    static_cast<RenderViewHostImpl*>(RenderViewHost::From(rwh))
        ->SetInitialFocus(focus_type == blink::kWebFocusTypeBackward);
  }
  RenderWidgetHostImpl::From(rwh)->GetWidgetInputHandler()->SetFocus(focused);
  if (!focused && mouse_locked_)
    DidUnlockMouse();

  // Restore the last seen state of text input to the view.
  RenderWidgetHostViewBase* rwhv = static_cast<RenderWidgetHostViewBase*>(
      rwh->GetView());
  SendTextInputTypeChangedToView(rwhv);
}

bool BrowserPluginGuest::LockMouse(bool allowed) {
  if (!attached() || (mouse_locked_ == allowed))
    return false;

  return embedder_web_contents()->GotResponseToLockMouseRequest(allowed);
}

WebContentsImpl* BrowserPluginGuest::CreateNewGuestWindow(
    const WebContents::CreateParams& params) {
  WebContentsImpl* new_contents =
      static_cast<WebContentsImpl*>(delegate_->CreateNewGuestWindow(params));
  DCHECK(new_contents);
  return new_contents;
}

bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
    const IPC::Message& message) {
  RenderWidgetHostViewGuest* rwhv = static_cast<RenderWidgetHostViewGuest*>(
      web_contents()->GetRenderWidgetHostView());

  // Until the guest is attached, it should not be handling input events.
  if (attached() && rwhv &&
      rwhv->OnMessageReceivedFromEmbedder(message,
                                          GetOwnerRenderWidgetHost())) {
    return true;
  }

  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
    IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Detach, OnDetach)
    IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate,
                        OnDragStatusUpdate)
    IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand,
                        OnExecuteEditCommand)
    IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExtendSelectionAndDelete,
                        OnExtendSelectionAndDelete)
    IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeCommitText, OnImeCommitText)

    IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeFinishComposingText,
                        OnImeFinishComposingText)

    IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeSetComposition,
                        OnImeSetComposition)
    IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK, OnLockMouseAck)
    IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent,
                        OnSetEditCommandsForNextKeyEvent)
    IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus, OnSetFocus)
    IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility, OnSetVisibility)
    IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK, OnUnlockMouseAck)
    IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SynchronizeVisualProperties,
                        OnSynchronizeVisualProperties)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void BrowserPluginGuest::InitInternal(
    const BrowserPluginHostMsg_Attach_Params& params,
    WebContentsImpl* owner_web_contents) {
  focused_ = params.focused;
  OnSetFocus(browser_plugin::kInstanceIDNone, focused_,
             blink::kWebFocusTypeNone);

  guest_visible_ = params.visible;
  UpdateVisibility();

  is_full_page_plugin_ = params.is_full_page_plugin;
  frame_rect_ = params.frame_rect;

  if (owner_web_contents_ != owner_web_contents) {
    WebContentsViewGuest* new_view = nullptr;
    if (!GuestMode::IsCrossProcessFrameGuest(GetWebContents())) {
      new_view =
          static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
    }

    if (owner_web_contents_ && new_view)
      new_view->OnGuestDetached(owner_web_contents_->GetView());

    // Once a BrowserPluginGuest has an embedder WebContents, it's considered to
    // be attached.
    owner_web_contents_ = owner_web_contents;
    if (new_view)
      new_view->OnGuestAttached(owner_web_contents_->GetView());
  }

  RendererPreferences* renderer_prefs =
      GetWebContents()->GetMutableRendererPrefs();
  std::string guest_user_agent_override = renderer_prefs->user_agent_override;
  // Copy renderer preferences (and nothing else) from the embedder's
  // WebContents to the guest.
  //
  // For GTK and Aura this is necessary to get proper renderer configuration
  // values for caret blinking interval, colors related to selection and
  // focus.
  *renderer_prefs = *owner_web_contents_->GetMutableRendererPrefs();
  renderer_prefs->user_agent_override = guest_user_agent_override;

  // Navigation is disabled in Chrome Apps. We want to make sure guest-initiated
  // navigations still continue to function inside the app.
  renderer_prefs->browser_handles_all_top_level_requests = false;
  // Disable "client blocked" error page for browser plugin.
  renderer_prefs->disable_client_blocked_error_page = true;

  embedder_visibility_observer_.reset(new EmbedderVisibilityObserver(this));

  DCHECK(GetWebContents()->GetRenderViewHost());

  // TODO(chrishtr): this code is wrong. The navigate_on_drag_drop field will
  // be reset again the next time preferences are updated.
  WebPreferences prefs =
      GetWebContents()->GetRenderViewHost()->GetWebkitPreferences();
  prefs.navigate_on_drag_drop = false;
  GetWebContents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs);

  SendMessageToEmbedder(std::make_unique<BrowserPluginMsg_Attach_ACK>(
      browser_plugin_instance_id()));
}

BrowserPluginGuest::~BrowserPluginGuest() {
}

// static
void BrowserPluginGuest::CreateInWebContents(
    WebContentsImpl* web_contents,
    BrowserPluginGuestDelegate* delegate) {
  auto guest = base::WrapUnique(new BrowserPluginGuest(
      web_contents->HasOpener(), web_contents, delegate));
  delegate->SetGuestHost(guest.get());
  web_contents->SetBrowserPluginGuest(std::move(guest));
}

// static
bool BrowserPluginGuest::IsGuest(WebContentsImpl* web_contents) {
  return web_contents && web_contents->GetBrowserPluginGuest();
}

// static
bool BrowserPluginGuest::IsGuest(RenderViewHostImpl* render_view_host) {
  return render_view_host && IsGuest(
      static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(
          render_view_host)));
}

RenderWidgetHostView* BrowserPluginGuest::GetOwnerRenderWidgetHostView() {
  if (RenderWidgetHostImpl* owner = GetOwnerRenderWidgetHost())
    return owner->GetView();
  return nullptr;
}

void BrowserPluginGuest::UpdateVisibility() {
  OnSetVisibility(browser_plugin_instance_id(), visible());
}

BrowserPluginGuestManager*
BrowserPluginGuest::GetBrowserPluginGuestManager() const {
  return GetWebContents()->GetBrowserContext()->GetGuestManager();
}

void BrowserPluginGuest::EmbedderVisibilityChanged(Visibility visibility) {
  embedder_visibility_ = visibility;
  UpdateVisibility();
}

void BrowserPluginGuest::PointerLockPermissionResponse(bool allow) {
  SendMessageToEmbedder(std::make_unique<BrowserPluginMsg_SetMouseLock>(
      browser_plugin_instance_id(), allow));
}

void BrowserPluginGuest::ResendEventToEmbedder(
    const blink::WebInputEvent& event) {
  if (!attached() || !owner_web_contents_)
    return;

  DCHECK(browser_plugin_instance_id_);
  RenderWidgetHostViewBase* view =
      static_cast<RenderWidgetHostViewBase*>(GetOwnerRenderWidgetHostView());

  gfx::Vector2d offset_from_embedder = frame_rect_.OffsetFromOrigin();
  if (event.GetType() == blink::WebInputEvent::kGestureScrollUpdate) {
    blink::WebGestureEvent resent_gesture_event;
    memcpy(&resent_gesture_event, &event, sizeof(blink::WebGestureEvent));
    resent_gesture_event.SetPositionInWidget(
        resent_gesture_event.PositionInWidget() + offset_from_embedder);
    // Mark the resend source with the browser plugin's instance id, so the
    // correct browser_plugin will know to ignore the event.
    resent_gesture_event.resending_plugin_id = browser_plugin_instance_id_;
    ui::LatencyInfo latency_info =
        ui::WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(
            resent_gesture_event);
    // The touch action may not be set for the embedder because the
    // GestureScrollBegin is sent to the guest view. In this case, set the touch
    // action of the embedder to Auto to prevent crash.
    GetOwnerRenderWidgetHost()->input_router()->ForceSetTouchActionAuto();
    view->ProcessGestureEvent(resent_gesture_event, latency_info);
  } else if (event.GetType() == blink::WebInputEvent::kMouseWheel) {
    blink::WebMouseWheelEvent resent_wheel_event;
    memcpy(&resent_wheel_event, &event, sizeof(blink::WebMouseWheelEvent));
    resent_wheel_event.SetPositionInWidget(
        resent_wheel_event.PositionInWidget().x + offset_from_embedder.x(),
        resent_wheel_event.PositionInWidget().y + offset_from_embedder.y());
    resent_wheel_event.resending_plugin_id = browser_plugin_instance_id_;
    // TODO(wjmaclean): Initialize latency info correctly for OOPIFs.
    // https://crbug.com/613628
    ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL);
    view->ProcessMouseWheelEvent(resent_wheel_event, latency_info);
  } else {
    NOTIMPLEMENTED();
  }
}

gfx::Point BrowserPluginGuest::GetCoordinatesInEmbedderWebContents(
    const gfx::Point& relative_point) {
  RenderWidgetHostView* owner_rwhv = GetOwnerRenderWidgetHostView();
  if (!owner_rwhv)
    return relative_point;

  gfx::Point point(relative_point);

  // Add the offset form the embedder web contents view.
  point += owner_rwhv->TransformPointToRootCoordSpace(frame_rect_.origin())
               .OffsetFromOrigin();
  if (embedder_web_contents()->GetBrowserPluginGuest()) {
    // |point| is currently with respect to the top-most view (outermost
    // WebContents). We should subtract a displacement to find the point with
    // resepct to embedder's WebContents.
    point -= owner_rwhv->TransformPointToRootCoordSpace(gfx::Point())
                 .OffsetFromOrigin();
  }

  return point;
}

WebContentsImpl* BrowserPluginGuest::GetWebContents() const {
  return static_cast<WebContentsImpl*>(web_contents());
}

gfx::Point BrowserPluginGuest::GetScreenCoordinates(
    const gfx::Point& relative_position) const {
  if (!attached())
    return relative_position;

  gfx::Point screen_pos(relative_position);
  screen_pos += frame_rect_.OffsetFromOrigin();
  return screen_pos;
}

void BrowserPluginGuest::SendMessageToEmbedder(
    std::unique_ptr<IPC::Message> msg) {
  // During tests, attache() may be true when there is no owner_web_contents_;
  // in this case just queue any messages we receive.
  if (!attached() || !owner_web_contents_) {
    // Some pages such as data URLs, javascript URLs, and about:blank
    // do not load external resources and so they load prior to attachment.
    // As a result, we must save all these IPCs until attachment and then
    // forward them so that the embedder gets a chance to see and process
    // the load events.
    pending_messages_.push_back(std::move(msg));
    return;
  }

  // If the guest is inside a cross-process frame, it is possible to get here
  // after the owner frame is detached. Then, the owner RenderWidgetHost will
  // be null and the message is dropped.
  if (auto* rwh = GetOwnerRenderWidgetHost())
    rwh->Send(msg.release());
}

void BrowserPluginGuest::DragSourceEndedAt(float client_x,
                                           float client_y,
                                           float screen_x,
                                           float screen_y,
                                           blink::WebDragOperation operation) {
  web_contents()->GetRenderViewHost()->GetWidget()->DragSourceEndedAt(
      gfx::PointF(client_x, client_y), gfx::PointF(screen_x, screen_y),
      operation);
  seen_embedder_drag_source_ended_at_ = true;
  EndSystemDragIfApplicable();
}

void BrowserPluginGuest::EndSystemDragIfApplicable() {
  // Ideally we'd want either WebDragStatusDrop or WebDragStatusLeave...
  // Call guest RVH->DragSourceSystemDragEnded() correctly on the guest where
  // the drag was initiated. Calling DragSourceSystemDragEnded() correctly
  // means we call it in all cases and also make sure we only call it once.
  // This ensures that the input state of the guest stays correct, otherwise
  // it will go stale and won't accept any further input events.
  //
  // The strategy used here to call DragSourceSystemDragEnded() on the RVH
  // is when the following conditions are met:
  //   a. Embedder has seen SystemDragEnded()
  //   b. Embedder has seen DragSourceEndedAt()
  //   c. The guest has seen some drag status update other than
  //      WebDragStatusUnknown. Note that this step should ideally be done
  //      differently: The guest has seen at least one of
  //      {WebDragStatusOver, WebDragStatusDrop}. However, if a user drags
  //      a source quickly outside of <webview> bounds, then the
  //      BrowserPluginGuest never sees any of these drag status updates,
  //      there we just check whether we've seen any drag status update or
  //      not.
  if (last_drag_status_ != blink::kWebDragStatusOver &&
      seen_embedder_drag_source_ended_at_ && seen_embedder_system_drag_ended_) {
    RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
        GetWebContents()->GetRenderViewHost());
    guest_rvh->GetWidget()->DragSourceSystemDragEnded();
    last_drag_status_ = blink::kWebDragStatusUnknown;
    seen_embedder_system_drag_ended_ = false;
    seen_embedder_drag_source_ended_at_ = false;
    ignore_dragged_url_ = true;
  }
}

void BrowserPluginGuest::EmbedderSystemDragEnded() {
  seen_embedder_system_drag_ended_ = true;
  EndSystemDragIfApplicable();
}

// TODO(wjmaclean): Replace this approach with ones based on std::function
// as in https://codereview.chromium.org/1404353004/ once all Chrome platforms
// support this. https://crbug.com/544212
std::unique_ptr<IPC::Message> BrowserPluginGuest::UpdateInstanceIdIfNecessary(
    std::unique_ptr<IPC::Message> msg) const {
  DCHECK(msg.get());

  int msg_browser_plugin_instance_id = browser_plugin::kInstanceIDNone;
  base::PickleIterator iter(*msg.get());
  if (!iter.ReadInt(&msg_browser_plugin_instance_id) ||
      msg_browser_plugin_instance_id != browser_plugin::kInstanceIDNone) {
    return msg;
  }

  // This method may be called with no browser_plugin_instance_id in tests.
  if (!browser_plugin_instance_id())
    return msg;

  std::unique_ptr<IPC::Message> new_msg(
      new IPC::Message(msg->routing_id(), msg->type(), msg->priority()));
  new_msg->WriteInt(browser_plugin_instance_id());

  // Copy remaining payload from original message.
  // TODO(wjmaclean): it would be nice if IPC::PickleIterator had a method
  // like 'RemainingBytes()' so that we don't have to include implementation-
  // specific details like sizeof() in the next line.
  DCHECK(msg->payload_size() >= sizeof(int));
  size_t remaining_bytes = msg->payload_size() - sizeof(int);
  // Some BrowserPluginMsgs only have the |browser_plugin_instance_id| and no
  // further payload. It they are enqueued, and require updating of the id, then
  // this would subsequently fail.
  // TODO(wjmaclean): It might be nice to enqueue the creation of the
  // IPC::Messages, rather than the messages themselves. Thus avoiding having to
  // perform custom read/writes.
  if (remaining_bytes) {
    const char* data = nullptr;
    bool read_success = iter.ReadBytes(&data, remaining_bytes);
    CHECK(read_success)
        << "Unexpected failure reading remaining IPC::Message payload.";
    new_msg->WriteBytes(data, remaining_bytes);
  }
  return new_msg;
}

void BrowserPluginGuest::SendQueuedMessages() {
  if (!attached())
    return;

  while (!pending_messages_.empty()) {
    std::unique_ptr<IPC::Message> message_ptr =
        std::move(pending_messages_.front());
    pending_messages_.pop_front();
    SendMessageToEmbedder(UpdateInstanceIdIfNecessary(std::move(message_ptr)));
  }
}

void BrowserPluginGuest::SendTextInputTypeChangedToView(
    RenderWidgetHostViewBase* guest_rwhv) {
  if (!guest_rwhv)
    return;

  if (!owner_web_contents_) {
    // If we were showing an interstitial, then we can end up here during
    // embedder shutdown or when the embedder navigates to a different page.
    // The call stack is roughly:
    // BrowserPluginGuest::SetFocus()
    // content::InterstitialPageImpl::Hide()
    // content::InterstitialPageImpl::DontProceed().
    //
    // TODO(lazyboy): Write a WebUI test once http://crbug.com/463674 is fixed.
    return;
  }

  if (last_text_input_state_.get()) {
    guest_rwhv->TextInputStateChanged(*last_text_input_state_);
    if (auto* rwh = guest_rwhv->host()) {
      // We need composition range information for some IMEs. To get the
      // updates, we need to explicitly ask the renderer to monitor and send the
      // composition information changes. RenderWidgetHostView of the page will
      // send the request to its process but the machinery for forwarding it to
      // BrowserPlugin is not there. Therefore, we send a direct request to the
      // guest process to start monitoring the state (see
      // https://crbug.com/714771).
      rwh->RequestCompositionUpdates(
          false, last_text_input_state_->type != ui::TEXT_INPUT_TYPE_NONE);
    }
  }
}

void BrowserPluginGuest::DidFinishNavigation(
    NavigationHandle* navigation_handle) {
  if (navigation_handle->HasCommitted())
    RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.DidNavigate"));
}

void BrowserPluginGuest::RenderViewReady() {
  if (GuestMode::IsCrossProcessFrameGuest(GetWebContents()))
    return;

  RenderViewHost* rvh = GetWebContents()->GetRenderViewHost();
  // TODO(fsamuel): Investigate whether it's possible to update state earlier
  // here (see http://crbug.com/158151).
  RenderWidgetHostImpl::From(rvh->GetWidget())
      ->GetWidgetInputHandler()
      ->SetFocus(focused_);
  UpdateVisibility();

  // In case we've created a new guest render process after a crash, let the
  // associated BrowserPlugin know. We only need to send this if we're attached,
  // as guest_crashed_ is cleared automatically on attach anyways.
  if (attached() && !features::IsMultiProcessMash()) {
    RenderWidgetHostViewGuest* rwhv = static_cast<RenderWidgetHostViewGuest*>(
        web_contents()->GetRenderWidgetHostView());
    if (rwhv) {
      SendMessageToEmbedder(std::make_unique<BrowserPluginMsg_GuestReady>(
          browser_plugin_instance_id(), rwhv->GetFrameSinkId()));
    }
  }

  RenderWidgetHostImpl::From(rvh->GetWidget())
      ->set_hung_renderer_delay(
          base::TimeDelta::FromMilliseconds(kHungRendererDelayMs));
}

void BrowserPluginGuest::RenderProcessGone(base::TerminationStatus status) {
  SendMessageToEmbedder(std::make_unique<BrowserPluginMsg_GuestGone>(
      browser_plugin_instance_id()));
  switch (status) {
#if defined(OS_CHROMEOS)
    case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
#endif
    case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
      RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Killed"));
      break;
    case base::TERMINATION_STATUS_PROCESS_CRASHED:
      RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Crashed"));
      break;
    case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
      RecordAction(
          base::UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath"));
      break;
    case base::TERMINATION_STATUS_LAUNCH_FAILED:
      RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.LaunchFailed"));
      break;
    default:
      break;
  }
}

void BrowserPluginGuest::DidSetHasTouchEventHandlers(bool accept) {
  SendMessageToEmbedder(
      std::make_unique<BrowserPluginMsg_ShouldAcceptTouchEvents>(
          browser_plugin_instance_id(), accept));
}

void BrowserPluginGuest::DidTextInputStateChange(const TextInputState& params) {
  // Save the state of text input so we can restore it on focus.
  last_text_input_state_ = std::make_unique<TextInputState>(params);

  SendTextInputTypeChangedToView(static_cast<RenderWidgetHostViewBase*>(
      web_contents()->GetRenderWidgetHostView()));
}

void BrowserPluginGuest::DidLockMouse(bool user_gesture, bool privileged) {
  if (pending_lock_request_) {
    // Immediately reject the lock because only one pointerLock may be active
    // at a time.
    RenderWidgetHost* widget_host =
        web_contents()->GetRenderViewHost()->GetWidget();
    widget_host->Send(
        new WidgetMsg_LockMouse_ACK(widget_host->GetRoutingID(), false));
    return;
  }

  pending_lock_request_ = true;

  RenderWidgetHostImpl* owner = GetOwnerRenderWidgetHost();
  bool is_last_unlocked_by_target =
      owner ? owner->is_last_unlocked_by_target() : false;

  delegate_->RequestPointerLockPermission(
      user_gesture, is_last_unlocked_by_target,
      base::BindRepeating(&BrowserPluginGuest::PointerLockPermissionResponse,
                          weak_ptr_factory_.GetWeakPtr()));
}

void BrowserPluginGuest::DidUnlockMouse() {
  SendMessageToEmbedder(std::make_unique<BrowserPluginMsg_SetMouseLock>(
      browser_plugin_instance_id(), false));
}

// static
bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
    const IPC::Message& message) {
  return (message.type() != BrowserPluginHostMsg_Attach::ID) &&
         (IPC_MESSAGE_CLASS(message) == BrowserPluginMsgStart);
}

bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  // In --site-per-process, we do not need most of BrowserPluginGuest to drive
  // inner WebContents.
  // TODO(lazyboy): Fix this as part of http://crbug.com/330264. The required
  // parts of code from this class should be extracted to a separate class for
  // --site-per-process.
  if (GuestMode::IsCrossProcessFrameGuest(GetWebContents()))
    return false;

  IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
    IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
    IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message,
                                           RenderFrameHost* render_frame_host) {
  // This will eventually be the home for more IPC handlers that depend on
  // RenderFrameHost. Until more are moved here, though, the IPC_* macros won't
  // compile if there are no handlers for a platform. So we have both #if guards
  // around the whole thing (unfortunate but temporary), and #if guards where
  // they belong, only around the one IPC handler. TODO(avi): Move more of the
  // frame-based handlers to this function and remove the outer #if layer.
#if defined(OS_MACOSX)
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(BrowserPluginGuest, message,
                                   render_frame_host)
    // MacOS X creates and populates platform-specific select drop-down menus
    // whereas other platforms merely create a popup window that the guest
    // renderer process paints inside.
    IPC_MESSAGE_HANDLER(FrameHostMsg_ShowPopup, OnShowPopup)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
#else
  return false;
#endif
}

void BrowserPluginGuest::Attach(
    int browser_plugin_instance_id,
    WebContentsImpl* embedder_web_contents,
    const BrowserPluginHostMsg_Attach_Params& params) {
  browser_plugin_instance_id_ = browser_plugin_instance_id;
  // The guest is owned by the embedder. Attach is queued up so we cannot
  // change embedders before attach completes. If the embedder goes away,
  // so does the guest and so we will never call WillAttachComplete because
  // we have a weak ptr.
  delegate_->WillAttach(
      embedder_web_contents, browser_plugin_instance_id,
      params.is_full_page_plugin,
      base::BindOnce(&BrowserPluginGuest::OnWillAttachComplete,
                     weak_ptr_factory_.GetWeakPtr(), embedder_web_contents,
                     params));
}

void BrowserPluginGuest::OnWillAttachComplete(
    WebContentsImpl* embedder_web_contents,
    const BrowserPluginHostMsg_Attach_Params& params) {
  // If a RenderView has already been created for this new window, then we need
  // to initialize the browser-side state now so that the RenderFrameHostManager
  // does not create a new RenderView on navigation.
  if (has_render_view_) {
    // This will trigger a callback to RenderViewReady after a round-trip IPC.
    static_cast<RenderViewHostImpl*>(GetWebContents()->GetRenderViewHost())
        ->GetWidget()
        ->Init();
    GetWebContents()->GetMainFrame()->Init();
    WebContentsViewGuest* web_contents_view =
        static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
    if (!web_contents()->GetRenderViewHost()->GetWidget()->GetView()) {
      web_contents_view->CreateViewForWidget(
          web_contents()->GetRenderViewHost()->GetWidget(), true);
    }
  }

  InitInternal(params, embedder_web_contents);

  attached_ = true;
  SendQueuedMessages();

  delegate_->DidAttach(GetGuestProxyRoutingID());
  RenderWidgetHostViewGuest* rwhv = static_cast<RenderWidgetHostViewGuest*>(
      web_contents()->GetRenderWidgetHostView());
  if (rwhv)
    rwhv->OnAttached();
  has_render_view_ = true;

  RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Attached"));
}

void BrowserPluginGuest::OnDetach(int browser_plugin_instance_id) {
  if (!attached())
    return;

  // It is important that the WebContents is notified before detaching.
  GetWebContents()->BrowserPluginGuestWillDetach();

  // This tells BrowserPluginGuest to queue up all IPCs to BrowserPlugin until
  // it's attached again.
  attached_ = false;

  RenderWidgetHostViewChildFrame* rwhv =
      static_cast<RenderWidgetHostViewChildFrame*>(
          web_contents()->GetRenderWidgetHostView());
  // If the guest is terminated, our host may already be gone.
  if (rwhv) {
    rwhv->UnregisterFrameSinkId();
    RenderWidgetHostViewBase* root_view =
        RenderWidgetHostViewGuest::GetRootView(rwhv);
    if (root_view)
      root_view->GetCursorManager()->ViewBeingDestroyed(rwhv);
  }

  delegate_->DidDetach();
}

void BrowserPluginGuest::OnDragStatusUpdate(int browser_plugin_instance_id,
                                            blink::WebDragStatus drag_status,
                                            const DropData& drop_data,
                                            blink::WebDragOperationsMask mask,
                                            const gfx::PointF& location) {
  RenderViewHost* host = GetWebContents()->GetRenderViewHost();
  auto* embedder = owner_web_contents_->GetBrowserPluginEmbedder();
  DropData filtered_data(drop_data);
  // TODO(paulmeyer): This will need to target the correct specific
  // RenderWidgetHost to work with OOPIFs. See crbug.com/647249.
  RenderWidgetHost* widget = host->GetWidget();
  widget->FilterDropData(&filtered_data);
  switch (drag_status) {
    case blink::kWebDragStatusEnter:
      widget->DragTargetDragEnter(filtered_data, location, location, mask,
                                  drop_data.key_modifiers);
      // Only track the URL being dragged over the guest if the link isn't
      // coming from the guest.
      if (!embedder->DragEnteredGuest(this))
        ignore_dragged_url_ = false;
      break;
    case blink::kWebDragStatusOver:
      widget->DragTargetDragOver(location, location, mask,
                                 drop_data.key_modifiers);
      break;
    case blink::kWebDragStatusLeave:
      embedder->DragLeftGuest(this);
      widget->DragTargetDragLeave(gfx::PointF(), gfx::PointF());
      ignore_dragged_url_ = true;
      break;
    case blink::kWebDragStatusDrop:
      widget->DragTargetDrop(filtered_data, location, location,
                             drop_data.key_modifiers);

      if (!ignore_dragged_url_ && filtered_data.url.is_valid())
        delegate_->DidDropLink(filtered_data.url);
      ignore_dragged_url_ = true;
      break;
    case blink::kWebDragStatusUnknown:
      ignore_dragged_url_ = true;
      NOTREACHED();
  }
  last_drag_status_ = drag_status;
  EndSystemDragIfApplicable();
}

void BrowserPluginGuest::OnExecuteEditCommand(int browser_plugin_instance_id,
                                              const std::string& name) {
  RenderFrameHostImpl* focused_frame =
      static_cast<RenderFrameHostImpl*>(web_contents()->GetFocusedFrame());
  if (!focused_frame)
    return;

  focused_frame->GetFrameInputHandler()->ExecuteEditCommand(name,
                                                            base::nullopt);
}

void BrowserPluginGuest::OnImeSetComposition(
    int browser_plugin_instance_id,
    const BrowserPluginHostMsg_SetComposition_Params& params) {
  std::vector<ui::ImeTextSpan> ui_ime_text_spans =
      ConvertBlinkImeTextSpansToUiImeTextSpans(params.ime_text_spans);
  GetWebContents()
      ->GetRenderViewHost()
      ->GetWidget()
      ->GetWidgetInputHandler()
      ->ImeSetComposition(params.text, ui_ime_text_spans,
                          params.replacement_range, params.selection_start,
                          params.selection_end);
}

void BrowserPluginGuest::OnImeCommitText(
    int browser_plugin_instance_id,
    const base::string16& text,
    const std::vector<blink::WebImeTextSpan>& ime_text_spans,
    const gfx::Range& replacement_range,
    int relative_cursor_pos) {
  std::vector<ui::ImeTextSpan> ui_ime_text_spans =
      ConvertBlinkImeTextSpansToUiImeTextSpans(ime_text_spans);
  GetWebContents()
      ->GetRenderViewHost()
      ->GetWidget()
      ->GetWidgetInputHandler()
      ->ImeCommitText(text, ui_ime_text_spans, replacement_range,
                      relative_cursor_pos, base::OnceClosure());
}

void BrowserPluginGuest::OnImeFinishComposingText(
    int browser_plugin_instance_id,
    bool keep_selection) {
  DCHECK_EQ(browser_plugin_instance_id_, browser_plugin_instance_id);
  GetWebContents()
      ->GetRenderViewHost()
      ->GetWidget()
      ->GetWidgetInputHandler()
      ->ImeFinishComposingText(keep_selection);
}

void BrowserPluginGuest::OnExtendSelectionAndDelete(
    int browser_plugin_instance_id,
    int before,
    int after) {
  RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
      web_contents()->GetFocusedFrame());
  if (rfh)
    rfh->GetFrameInputHandler()->ExtendSelectionAndDelete(before, after);
}

void BrowserPluginGuest::OnLockMouseAck(int browser_plugin_instance_id,
                                        bool succeeded) {
  RenderWidgetHost* widget_host =
      web_contents()->GetRenderViewHost()->GetWidget();
  widget_host->Send(
      new WidgetMsg_LockMouse_ACK(widget_host->GetRoutingID(), succeeded));
  pending_lock_request_ = false;
  if (succeeded)
    mouse_locked_ = true;
}

void BrowserPluginGuest::OnSetFocus(int browser_plugin_instance_id,
                                    bool focused,
                                    blink::WebFocusType focus_type) {
  RenderWidgetHostView* rwhv = web_contents()->GetRenderWidgetHostView();
  RenderWidgetHost* rwh = rwhv ? rwhv->GetRenderWidgetHost() : nullptr;
  SetFocus(rwh, focused, focus_type);
}

void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent(
    int browser_plugin_instance_id,
    const std::vector<EditCommand>& edit_commands) {
  GetWebContents()
      ->GetRenderViewHost()
      ->GetWidget()
      ->GetWidgetInputHandler()
      ->SetEditCommandsForNextKeyEvent(edit_commands);
}

void BrowserPluginGuest::OnSetVisibility(int browser_plugin_instance_id,
                                         bool visible) {
  // For OOPIF-<webivew>, the remote frame will handle visibility state.
  if (GuestMode::IsCrossProcessFrameGuest(GetWebContents()))
    return;

  guest_visible_ = visible;

  // Do not use WebContents::UpdateWebContentsVisibility() because it ignores
  // visibility changes that come before the first change to VISIBLE.
  if (!guest_visible_ || embedder_visibility_ == Visibility::HIDDEN)
    GetWebContents()->WasHidden();
  else if (embedder_visibility_ == Visibility::VISIBLE)
    GetWebContents()->WasShown();
  else
    GetWebContents()->WasOccluded();
}

void BrowserPluginGuest::OnUnlockMouseAck(int browser_plugin_instance_id) {
  // mouse_locked_ could be false here if the lock attempt was cancelled due
  // to window focus, or for various other reasons before the guest was informed
  // of the lock's success.
  if (mouse_locked_) {
    RenderWidgetHost* widget_host =
        web_contents()->GetRenderViewHost()->GetWidget();
    widget_host->Send(new WidgetMsg_MouseLockLost(widget_host->GetRoutingID()));
  }
  mouse_locked_ = false;
}

void BrowserPluginGuest::OnSynchronizeVisualProperties(
    int browser_plugin_instance_id,
    const FrameVisualProperties& visual_properties) {
  if ((local_surface_id_allocation_.local_surface_id() >
       visual_properties.local_surface_id_allocation.local_surface_id()) ||
      ((frame_rect_.size() != visual_properties.screen_space_rect.size() ||
        screen_info_ != visual_properties.screen_info ||
        capture_sequence_number_ != visual_properties.capture_sequence_number ||
        zoom_level_ != visual_properties.zoom_level) &&
       local_surface_id_allocation_.local_surface_id() ==
           visual_properties.local_surface_id_allocation.local_surface_id())) {
    SiteInstance* owner_site_instance = delegate_->GetOwnerSiteInstance();
    bad_message::ReceivedBadMessage(
        owner_site_instance->GetProcess(),
        bad_message::BPG_RESIZE_PARAMS_CHANGED_LOCAL_SURFACE_ID_UNCHANGED);
    return;
  }

  screen_info_ = visual_properties.screen_info;
  frame_rect_ = visual_properties.screen_space_rect;
  zoom_level_ = visual_properties.zoom_level;

  GetWebContents()->SendScreenRects();
  local_surface_id_allocation_ = visual_properties.local_surface_id_allocation;
  bool capture_sequence_number_changed =
      capture_sequence_number_ != visual_properties.capture_sequence_number;
  capture_sequence_number_ = visual_properties.capture_sequence_number;

  RenderWidgetHostView* view = web_contents()->GetRenderWidgetHostView();
  if (!view)
    return;

  // We could add functionality to set a specific capture sequence number on the
  // |view|, but knowing that it's changed is sufficient for us simply request
  // that our RenderWidgetHostView synchronizes its surfaces. Note that this
  // should only happen during web tests, since that is the only call that
  // should trigger the capture sequence number to change.
  if (capture_sequence_number_changed)
    view->EnsureSurfaceSynchronizedForWebTest();

  RenderWidgetHostImpl* render_widget_host =
      RenderWidgetHostImpl::From(view->GetRenderWidgetHost());
  DCHECK(render_widget_host);

  render_widget_host->SetAutoResize(visual_properties.auto_resize_enabled,
                                    visual_properties.min_size_for_auto_resize,
                                    visual_properties.max_size_for_auto_resize);

  render_widget_host->SynchronizeVisualProperties();
}

#if defined(OS_MACOSX)
void BrowserPluginGuest::OnShowPopup(
    RenderFrameHost* render_frame_host,
    const FrameHostMsg_ShowPopup_Params& params) {
  gfx::Rect translated_bounds(params.bounds);
  WebContents* guest = web_contents();
  if (GuestMode::IsCrossProcessFrameGuest(guest)) {
    translated_bounds.set_origin(
        guest->GetRenderWidgetHostView()->TransformPointToRootCoordSpace(
            translated_bounds.origin()));
  } else {
    translated_bounds.Offset(frame_rect_.OffsetFromOrigin());
  }
  BrowserPluginPopupMenuHelper popup_menu_helper(
      owner_web_contents_->GetMainFrame(), render_frame_host);
  popup_menu_helper.ShowPopupMenu(translated_bounds,
                                  params.item_height,
                                  params.item_font_size,
                                  params.selected_item,
                                  params.popup_items,
                                  params.right_aligned,
                                  params.allow_multiple_selection);
}
#endif

void BrowserPluginGuest::OnShowWidget(int widget_route_id,
                                      const gfx::Rect& initial_rect) {
  int process_id = GetWebContents()->GetMainFrame()->GetProcess()->GetID();
  GetWebContents()->ShowCreatedWidget(process_id, widget_route_id,
                                      initial_rect);
}

void BrowserPluginGuest::OnTakeFocus(bool reverse) {
  SendMessageToEmbedder(std::make_unique<BrowserPluginMsg_AdvanceFocus>(
      browser_plugin_instance_id(), reverse));
}

}  // namespace content
