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

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),
      owner_web_contents_(nullptr),
      attached_(false),
      has_attached_since_surface_set_(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"));
  web_contents->SetBrowserPluginGuest(this);
  delegate->SetGuestHost(this);
}

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);
}

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_)
    OnUnlockMouse();

  // 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);

  base::Optional<viz::LocalSurfaceId> child_local_surface_id;
  if (local_surface_id_.is_valid())
    child_local_surface_id = local_surface_id_;
  SendMessageToEmbedder(std::make_unique<BrowserPluginMsg_Attach_ACK>(
      browser_plugin_instance_id(), child_local_surface_id));
}

BrowserPluginGuest::~BrowserPluginGuest() {
}

// static
BrowserPluginGuest* BrowserPluginGuest::Create(
    WebContentsImpl* web_contents,
    BrowserPluginGuestDelegate* delegate) {
  return new BrowserPluginGuest(
      web_contents->HasOpener(), web_contents, delegate);
}

// 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::SetChildFrameSurface(
    const viz::SurfaceInfo& surface_info) {
  has_attached_since_surface_set_ = false;
  if (!base::FeatureList::IsEnabled(::features::kMash)) {
    SendMessageToEmbedder(
        std::make_unique<BrowserPluginMsg_SetChildFrameSurface>(
            browser_plugin_instance_id(), surface_info));
  }
}

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);
    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);
  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() && !base::FeatureList::IsEnabled(::features::kMash)) {
    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;
  }
}

// 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_HasTouchEventHandlers,
                        OnHasTouchEventHandlers)
    IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
    IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
    IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
    IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
                        OnTextInputStateChanged)
    IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
    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::Bind(&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;
  has_attached_since_surface_set_ = 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);
}

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::OnLockMouse(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 ViewMsg_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::Bind(&BrowserPluginGuest::PointerLockPermissionResponse,
                 weak_ptr_factory_.GetWeakPtr()));
}

void BrowserPluginGuest::OnLockMouseAck(int browser_plugin_instance_id,
                                        bool succeeded) {
  RenderWidgetHost* widget_host =
      web_contents()->GetRenderViewHost()->GetWidget();
  widget_host->Send(
      new ViewMsg_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::OnUnlockMouse() {
  SendMessageToEmbedder(std::make_unique<BrowserPluginMsg_SetMouseLock>(
      browser_plugin_instance_id(), false));
}

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 ViewMsg_MouseLockLost(widget_host->GetRoutingID()));
  }
  mouse_locked_ = false;
}

void BrowserPluginGuest::OnSynchronizeVisualProperties(
    int browser_plugin_instance_id,
    const viz::LocalSurfaceId& local_surface_id,
    const FrameVisualProperties& visual_properties) {
  if (local_surface_id_ > 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) &&
       local_surface_id_ == 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;
  GetWebContents()->SendScreenRects();
  local_surface_id_ = local_surface_id;
  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 layout tests, since that is the only call that
  // should trigger the capture sequence number to change.
  if (capture_sequence_number_changed)
    view->EnsureSurfaceSynchronizedForLayoutTest();

  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();
}

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

#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 route_id,
                                      const gfx::Rect& initial_rect) {
  int process_id = GetWebContents()->GetMainFrame()->GetProcess()->GetID();
  GetWebContents()->ShowCreatedWidget(process_id, route_id, initial_rect);
}

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

void BrowserPluginGuest::OnTextInputStateChanged(const TextInputState& params) {
  // Save the state of text input so we can restore it on focus.
  last_text_input_state_.reset(new TextInputState(params));

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

}  // namespace content
