// Copyright 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/renderer/browser_plugin/browser_plugin.h"

#include <stddef.h>

#include <map>
#include <string>
#include <utility>
#include <vector>

#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/viz/common/features.h"
#include "components/viz/common/surfaces/surface_info.h"
#include "content/common/browser_plugin/browser_plugin_constants.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/view_messages.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/renderer/browser_plugin_delegate.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/renderer/accessibility/render_accessibility_impl.h"
#include "content/renderer/browser_plugin/browser_plugin_manager.h"
#include "content/renderer/child_frame_compositing_helper.h"
#include "content/renderer/cursor_utils.h"
#include "content/renderer/drop_data_builder.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/sad_plugin.h"
#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/public/platform/web_gesture_event.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
#include "third_party/blink/public/platform/web_rect.h"
#include "third_party/blink/public/web/web_ax_object.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_element.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_plugin_container.h"
#include "third_party/blink/public/web/web_view.h"
#include "ui/base/ui_base_features.h"
#include "ui/events/keycodes/keyboard_codes.h"

#if defined(USE_AURA)
#include "content/renderer/mus/mus_embedded_frame.h"
#include "content/renderer/mus/renderer_window_tree_client.h"
#endif

using blink::WebPluginContainer;
using blink::WebPoint;
using blink::WebRect;
using blink::WebURL;
using blink::WebVector;

namespace {

using PluginContainerMap =
    std::map<blink::WebPluginContainer*, content::BrowserPlugin*>;
static base::LazyInstance<PluginContainerMap>::DestructorAtExit
    g_plugin_container_map = LAZY_INSTANCE_INITIALIZER;

}  // namespace

namespace content {

// static
BrowserPlugin* BrowserPlugin::GetFromNode(blink::WebNode& node) {
  blink::WebPluginContainer* container = node.PluginContainer();
  if (!container)
    return nullptr;

  PluginContainerMap* browser_plugins = g_plugin_container_map.Pointer();
  PluginContainerMap::iterator it = browser_plugins->find(container);
  return it == browser_plugins->end() ? nullptr : it->second;
}

BrowserPlugin::BrowserPlugin(
    RenderFrame* render_frame,
    const base::WeakPtr<BrowserPluginDelegate>& delegate)
    : attached_(false),
      render_frame_routing_id_(render_frame->GetRoutingID()),
      container_(nullptr),
      guest_crashed_(false),
      plugin_focused_(false),
      visible_(true),
      mouse_locked_(false),
      ready_(false),
      browser_plugin_instance_id_(browser_plugin::kInstanceIDNone),
      delegate_(delegate),
      task_runner_(
          render_frame->GetTaskRunner(blink::TaskType::kInternalDefault)),
      weak_ptr_factory_(this) {
  browser_plugin_instance_id_ =
      BrowserPluginManager::Get()->GetNextInstanceID();

  if (delegate_)
    delegate_->SetElementInstanceID(browser_plugin_instance_id_);

  enable_surface_synchronization_ = features::IsSurfaceSynchronizationEnabled();
}

BrowserPlugin::~BrowserPlugin() {
  Detach();

  if (delegate_) {
    delegate_->DidDestroyElement();
    delegate_.reset();
  }

  BrowserPluginManager::Get()->RemoveBrowserPlugin(browser_plugin_instance_id_);
}

bool BrowserPlugin::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(BrowserPlugin, message)
    IPC_MESSAGE_HANDLER(BrowserPluginMsg_AdvanceFocus, OnAdvanceFocus)
    IPC_MESSAGE_HANDLER(BrowserPluginMsg_Attach_ACK, OnAttachACK)
    IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestGone, OnGuestGone)
    IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestReady, OnGuestReady)
    IPC_MESSAGE_HANDLER(BrowserPluginMsg_EnableAutoResize, OnEnableAutoResize)
    IPC_MESSAGE_HANDLER(BrowserPluginMsg_DisableAutoResize, OnDisableAutoResize)
    IPC_MESSAGE_HANDLER(BrowserPluginMsg_DidUpdateVisualProperties,
                        OnDidUpdateVisualProperties)
    IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetCursor, OnSetCursor)
    IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetMouseLock, OnSetMouseLock)
#if defined(USE_AURA)
    IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetMusEmbedToken, OnSetMusEmbedToken)
#endif
    IPC_MESSAGE_HANDLER(BrowserPluginMsg_ShouldAcceptTouchEvents,
                        OnShouldAcceptTouchEvents)
    IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetChildFrameSurface,
                        OnSetChildFrameSurface)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void BrowserPlugin::OnSetChildFrameSurface(
    int browser_plugin_instance_id,
    const viz::SurfaceInfo& surface_info) {
  if (!attached() || base::FeatureList::IsEnabled(features::kMash))
    return;

  if (!enable_surface_synchronization_) {
    compositing_helper_->SetPrimarySurfaceId(
        surface_info.id(), screen_space_rect().size(),
        cc::DeadlinePolicy::UseDefaultDeadline());
  }
  compositing_helper_->SetFallbackSurfaceId(surface_info.id(),
                                            screen_space_rect().size());
}

void BrowserPlugin::UpdateDOMAttribute(const std::string& attribute_name,
                                       const base::string16& attribute_value) {
  if (!Container())
    return;

  blink::WebElement element = Container()->GetElement();
  element.SetAttribute(blink::WebString::FromUTF8(attribute_name),
                       blink::WebString::FromUTF16(attribute_value));
}

void BrowserPlugin::Attach() {
  Detach();

  BrowserPluginHostMsg_Attach_Params attach_params;
  attach_params.focused = ShouldGuestBeFocused();
  attach_params.visible = visible_;
  attach_params.frame_rect = screen_space_rect();
  attach_params.is_full_page_plugin = false;
  if (Container()) {
    blink::WebLocalFrame* frame = Container()->GetDocument().GetFrame();
    attach_params.is_full_page_plugin =
        frame->View()->MainFrame()->IsWebLocalFrame() &&
        frame->View()
            ->MainFrame()
            ->ToWebLocalFrame()
            ->GetDocument()
            .IsPluginDocument();
  }
#if defined(USE_AURA)
  if (pending_embed_token_) {
    base::Optional<base::UnguessableToken> embed_token =
        std::move(pending_embed_token_);
    CreateMusWindowAndEmbed(*embed_token);
  }
#endif

  BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_Attach(
      render_frame_routing_id_,
      browser_plugin_instance_id_,
      attach_params));

  // Post an update event to the associated accessibility object.
  auto* render_frame =
      RenderFrameImpl::FromRoutingID(render_frame_routing_id());
  if (render_frame && render_frame->render_accessibility() && Container()) {
    blink::WebElement element = Container()->GetElement();
    blink::WebAXObject ax_element = blink::WebAXObject::FromWebNode(element);
    if (!ax_element.IsDetached()) {
      render_frame->render_accessibility()->HandleAXEvent(
          ax_element, ax::mojom::Event::kChildrenChanged);
    }
  }

  sent_visual_properties_ = base::nullopt;
}

void BrowserPlugin::Detach() {
  if (!attached())
    return;

  attached_ = false;
  guest_crashed_ = false;
  embedded_layer_ = nullptr;

  BrowserPluginManager::Get()->Send(
      new BrowserPluginHostMsg_Detach(browser_plugin_instance_id_));
}

const viz::LocalSurfaceId& BrowserPlugin::GetLocalSurfaceId() const {
  return parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId();
}

#if defined(USE_AURA)
void BrowserPlugin::CreateMusWindowAndEmbed(
    const base::UnguessableToken& embed_token) {
  RenderFrameImpl* render_frame =
      RenderFrameImpl::FromRoutingID(render_frame_routing_id_);
  if (!render_frame) {
    pending_embed_token_ = embed_token;
    return;
  }
  RendererWindowTreeClient* renderer_window_tree_client =
      RendererWindowTreeClient::Get(
          render_frame->GetRenderWidget()->routing_id());
  DCHECK(renderer_window_tree_client);
  mus_embedded_frame_ =
      renderer_window_tree_client->CreateMusEmbeddedFrame(this, embed_token);
  if (attached() && GetLocalSurfaceId().is_valid()) {
    mus_embedded_frame_->SetWindowBounds(GetLocalSurfaceId(),
                                         FrameRectInPixels());
  }
}
#endif

void BrowserPlugin::SynchronizeVisualProperties() {
  bool size_changed = !sent_visual_properties_ ||
                      sent_visual_properties_->auto_resize_enabled !=
                          pending_visual_properties_.auto_resize_enabled ||
                      sent_visual_properties_->min_size_for_auto_resize !=
                          pending_visual_properties_.min_size_for_auto_resize ||
                      sent_visual_properties_->max_size_for_auto_resize !=
                          pending_visual_properties_.max_size_for_auto_resize ||
                      sent_visual_properties_->local_frame_size !=
                          pending_visual_properties_.local_frame_size ||
                      sent_visual_properties_->screen_space_rect.size() !=
                          pending_visual_properties_.screen_space_rect.size();

  // Note that the following flag is true if the capture sequence number
  // actually changed. That is, it is false if we did not have
  // |sent_visual_properties_|, which is different from the other local flags
  // here.
  bool capture_sequence_number_changed =
      sent_visual_properties_ &&
      sent_visual_properties_->capture_sequence_number !=
          pending_visual_properties_.capture_sequence_number;

  bool synchronized_props_changed =
      !sent_visual_properties_ || size_changed ||
      sent_visual_properties_->screen_info !=
          pending_visual_properties_.screen_info ||
      capture_sequence_number_changed;

  if (synchronized_props_changed)
    parent_local_surface_id_allocator_.GenerateId();

  if (enable_surface_synchronization_ && frame_sink_id_.is_valid()) {
    // If we're synchronizing surfaces, then use an infinite deadline to ensure
    // everything is synchronized.
    cc::DeadlinePolicy deadline =
        capture_sequence_number_changed
            ? cc::DeadlinePolicy::UseInfiniteDeadline()
            : cc::DeadlinePolicy::UseDefaultDeadline();
    compositing_helper_->SetPrimarySurfaceId(
        viz::SurfaceId(frame_sink_id_, GetLocalSurfaceId()),
        screen_space_rect().size(), deadline);
  }

  bool position_changed =
      !sent_visual_properties_ ||
      sent_visual_properties_->screen_space_rect.origin() !=
          pending_visual_properties_.screen_space_rect.origin();
  bool visual_properties_changed =
      synchronized_props_changed || position_changed;

  if (visual_properties_changed && attached()) {
    // Let the browser know about the updated view rect.
    BrowserPluginManager::Get()->Send(
        new BrowserPluginHostMsg_SynchronizeVisualProperties(
            browser_plugin_instance_id_, GetLocalSurfaceId(),
            pending_visual_properties_));
  }

  if (delegate_ && size_changed)
    delegate_->DidResizeElement(screen_space_rect().size());

  if (visual_properties_changed && attached())
    sent_visual_properties_ = pending_visual_properties_;

#if defined(USE_AURA)
  if (features::IsMashEnabled() && mus_embedded_frame_) {
    mus_embedded_frame_->SetWindowBounds(GetLocalSurfaceId(),
                                         FrameRectInPixels());
  }
#endif
}

void BrowserPlugin::OnAdvanceFocus(int browser_plugin_instance_id,
                                   bool reverse) {
  auto* render_frame =
      RenderFrameImpl::FromRoutingID(render_frame_routing_id());
  auto* render_view = render_frame ? render_frame->GetRenderView() : nullptr;
  if (!render_view)
    return;
  render_view->GetWebView()->AdvanceFocus(reverse);
}

void BrowserPlugin::OnAttachACK(
    int browser_plugin_instance_id,
    const base::Optional<viz::LocalSurfaceId>& child_local_surface_id) {
  attached_ = true;
  if (child_local_surface_id)
    parent_local_surface_id_allocator_.Reset(*child_local_surface_id);
  SynchronizeVisualProperties();
}

void BrowserPlugin::OnGuestGone(int browser_plugin_instance_id) {
  guest_crashed_ = true;
  compositing_helper_->ChildFrameGone(screen_space_rect().size(),
                                      screen_info().device_scale_factor);
}

void BrowserPlugin::OnGuestReady(int browser_plugin_instance_id,
                                 const viz::FrameSinkId& frame_sink_id) {
  guest_crashed_ = false;
  frame_sink_id_ = frame_sink_id;
  sent_visual_properties_ = base::nullopt;
  SynchronizeVisualProperties();
}

void BrowserPlugin::OnDidUpdateVisualProperties(
    int browser_plugin_instance_id,
    const cc::RenderFrameMetadata& metadata) {
  if (!parent_local_surface_id_allocator_.UpdateFromChild(
          metadata.local_surface_id.value_or(viz::LocalSurfaceId()))) {
    return;
  }

  // The viz::LocalSurfaceId has changed so we call SynchronizeVisualProperties
  // here to embed it.
  SynchronizeVisualProperties();
}

void BrowserPlugin::OnEnableAutoResize(int browser_plugin_instance_id,
                                       const gfx::Size& min_size,
                                       const gfx::Size& max_size) {
  pending_visual_properties_.auto_resize_enabled = true;
  pending_visual_properties_.min_size_for_auto_resize = min_size;
  pending_visual_properties_.max_size_for_auto_resize = max_size;
  SynchronizeVisualProperties();
}

void BrowserPlugin::OnDisableAutoResize(int browser_plugin_instance_id) {
  pending_visual_properties_.auto_resize_enabled = false;
  SynchronizeVisualProperties();
}

void BrowserPlugin::OnSetCursor(int browser_plugin_instance_id,
                                const WebCursor& cursor) {
  cursor_ = cursor;
}

void BrowserPlugin::OnSetMouseLock(int browser_plugin_instance_id,
                                   bool enable) {
  RenderWidget* render_widget = GetMainWidget();
  if (enable) {
    if (mouse_locked_ || !render_widget)
      return;
    render_widget->mouse_lock_dispatcher()->LockMouse(this);
  } else {
    if (!mouse_locked_) {
      OnLockMouseACK(false);
      return;
    }
    if (!render_widget)
      return;
    render_widget->mouse_lock_dispatcher()->UnlockMouse(this);
  }
}

#if defined(USE_AURA)
void BrowserPlugin::OnSetMusEmbedToken(
    int instance_id,
    const base::UnguessableToken& embed_token) {
  DCHECK(base::FeatureList::IsEnabled(features::kMash));
  if (!attached_) {
    pending_embed_token_ = embed_token;
  } else {
    pending_embed_token_.reset();
    CreateMusWindowAndEmbed(embed_token);
  }
}
#endif

void BrowserPlugin::OnShouldAcceptTouchEvents(int browser_plugin_instance_id,
                                              bool accept) {
  if (Container()) {
    Container()->RequestTouchEventType(
        accept ? WebPluginContainer::kTouchEventRequestTypeRaw
               : WebPluginContainer::kTouchEventRequestTypeNone);
  }
}

gfx::Rect BrowserPlugin::FrameRectInPixels() const {
  const float device_scale_factor = GetDeviceScaleFactor();
  return gfx::Rect(
      gfx::ScaleToFlooredPoint(screen_space_rect().origin(),
                               device_scale_factor),
      gfx::ScaleToCeiledSize(screen_space_rect().size(), device_scale_factor));
}

float BrowserPlugin::GetDeviceScaleFactor() const {
  return pending_visual_properties_.screen_info.device_scale_factor;
}

RenderWidget* BrowserPlugin::GetMainWidget() const {
  RenderFrameImpl* frame =
      RenderFrameImpl::FromRoutingID(render_frame_routing_id());
  if (frame) {
    RenderViewImpl* render_view =
        static_cast<RenderViewImpl*>(frame->GetRenderView());
    if (render_view) {
      return render_view->GetWidget();
    }
  }

  return nullptr;
}

void BrowserPlugin::UpdateInternalInstanceId() {
  // This is a way to notify observers of our attributes that this plugin is
  // available in render tree.
  // TODO(lazyboy): This should be done through the delegate instead. Perhaps
  // by firing an event from there.
  UpdateDOMAttribute(
      "internalinstanceid",
      base::UTF8ToUTF16(base::IntToString(browser_plugin_instance_id_)));
}

void BrowserPlugin::UpdateGuestFocusState(blink::WebFocusType focus_type) {
  if (!attached())
    return;
  bool should_be_focused = ShouldGuestBeFocused();
  BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_SetFocus(
      browser_plugin_instance_id_,
      should_be_focused,
      focus_type));
}

void BrowserPlugin::ScreenInfoChanged(const ScreenInfo& screen_info) {
  pending_visual_properties_.screen_info = screen_info;
  if (guest_crashed_) {
    // Update the sad page to match the current ScreenInfo.
    compositing_helper_->ChildFrameGone(screen_space_rect().size(),
                                        screen_info.device_scale_factor);
    return;
  }
  SynchronizeVisualProperties();
}

void BrowserPlugin::UpdateCaptureSequenceNumber(
    uint32_t capture_sequence_number) {
  pending_visual_properties_.capture_sequence_number = capture_sequence_number;
  SynchronizeVisualProperties();
}

bool BrowserPlugin::ShouldGuestBeFocused() const {
  bool embedder_focused = false;
  RenderWidget* render_widget = GetMainWidget();
  if (render_widget)
    embedder_focused = render_widget->has_focus();
  return plugin_focused_ && embedder_focused;
}

WebPluginContainer* BrowserPlugin::Container() const {
  return container_;
}

bool BrowserPlugin::Initialize(WebPluginContainer* container) {
  DCHECK(container);
  DCHECK_EQ(this, container->Plugin());

  container_ = container;
  container_->SetWantsWheelEvents(true);

  g_plugin_container_map.Get().insert(std::make_pair(container_, this));

  BrowserPluginManager::Get()->AddBrowserPlugin(
      browser_plugin_instance_id_, this);

  // Defer attach call so that if there's any pending browser plugin
  // destruction, then it can progress first.
  task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&BrowserPlugin::UpdateInternalInstanceId,
                                weak_ptr_factory_.GetWeakPtr()));

  compositing_helper_ = std::make_unique<ChildFrameCompositingHelper>(this);

  embedding_render_widget_ =
      RenderFrameImpl::FromWebFrame(container_->GetDocument().GetFrame())
          ->GetRenderWidget()
          ->AsWeakPtr();
  embedding_render_widget_->RegisterBrowserPlugin(this);

  return true;
}

void BrowserPlugin::Destroy() {
  if (embedding_render_widget_) {
    embedding_render_widget_->UnregisterBrowserPlugin(this);
    embedding_render_widget_ = nullptr;
  }

  if (container_) {
    // The BrowserPlugin's WebPluginContainer is deleted immediately after this
    // call returns, so let's not keep a reference to it around.
    g_plugin_container_map.Get().erase(container_);
  }

  container_ = nullptr;
  // Will be a no-op if the mouse is not currently locked.
  RenderWidget* render_widget = GetMainWidget();
  if (render_widget)
    render_widget->mouse_lock_dispatcher()->OnLockTargetDestroyed(this);

  task_runner_->DeleteSoon(FROM_HERE, this);
}

v8::Local<v8::Object> BrowserPlugin::V8ScriptableObject(v8::Isolate* isolate) {
  if (!delegate_)
    return v8::Local<v8::Object>();

  return delegate_->V8ScriptableObject(isolate);
}

bool BrowserPlugin::SupportsKeyboardFocus() const {
  return visible_;
}

bool BrowserPlugin::SupportsEditCommands() const {
  return true;
}

bool BrowserPlugin::SupportsInputMethod() const {
  return true;
}

bool BrowserPlugin::CanProcessDrag() const {
  return true;
}

// static
bool BrowserPlugin::ShouldForwardToBrowserPlugin(
    const IPC::Message& message) {
  return IPC_MESSAGE_CLASS(message) == BrowserPluginMsgStart;
}

void BrowserPlugin::UpdateGeometry(const WebRect& plugin_rect_in_viewport,
                                   const WebRect& clip_rect,
                                   const WebRect& unobscured_rect,
                                   bool is_visible) {
  // Ignore this call during teardown. If the embedding RenderWidget is gone,
  // don't bother sending new geometry to the child because it's not being shown
  // anymore.
  if (!embedding_render_widget_)
    return;

  // Convert the plugin_rect_in_viewport to window coordinates, which is css.
  WebRect rect_in_css(plugin_rect_in_viewport);

  // We will use the local root's RenderWidget to convert coordinates to Window.
  // If this local root belongs to an OOPIF, on the browser side we will have to
  // consider the displacement of the child frame in root window.
  embedding_render_widget_->ConvertViewportToWindow(&rect_in_css);
  gfx::Rect screen_space_rect = rect_in_css;

  if (!ready_) {
    if (delegate_)
      delegate_->Ready();
    ready_ = true;
  }

  pending_visual_properties_.screen_space_rect = screen_space_rect;
  if (guest_crashed_) {
    // Update the sad page to match the current ScreenInfo.
    compositing_helper_->ChildFrameGone(screen_space_rect.size(),
                                        screen_info().device_scale_factor);
    return;
  }
  SynchronizeVisualProperties();
}

void BrowserPlugin::UpdateFocus(bool focused, blink::WebFocusType focus_type) {
  plugin_focused_ = focused;
  UpdateGuestFocusState(focus_type);
}

void BrowserPlugin::UpdateVisibility(bool visible) {
  if (visible_ == visible)
    return;

  visible_ = visible;
  if (!attached())
    return;

  compositing_helper_->UpdateVisibility(visible);

  BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_SetVisibility(
      browser_plugin_instance_id_,
      visible));
}

blink::WebInputEventResult BrowserPlugin::HandleInputEvent(
    const blink::WebCoalescedInputEvent& coalesced_event,
    blink::WebCursorInfo& cursor_info) {
  const blink::WebInputEvent& event = coalesced_event.Event();
  if (guest_crashed_ || !attached())
    return blink::WebInputEventResult::kNotHandled;

  DCHECK(!blink::WebInputEvent::IsTouchEventType(event.GetType()));

  // With direct event routing turned on, BrowserPlugin should almost never
  // see wheel events any more. The two exceptions are (1) scroll bubbling, and
  // (2) synthetic mouse wheels generated by touchpad GesturePinch events on
  // Mac, which always go to the mainframe and thus may hit BrowserPlugin if
  // it's in a top-level embedder. In both cases we should indicate the event
  // as not handled (for GesturePinch on Mac, indicating the event has been
  // handled leads to touchpad pinch not working).
  if (event.GetType() == blink::WebInputEvent::kMouseWheel)
    return blink::WebInputEventResult::kNotHandled;

  if (blink::WebInputEvent::IsGestureEventType(event.GetType())) {
    auto gesture_event = static_cast<const blink::WebGestureEvent&>(event);
    DCHECK(blink::WebInputEvent::kGestureTapDown == event.GetType() ||
           gesture_event.resending_plugin_id == browser_plugin_instance_id_);

    // We shouldn't be forwarding GestureEvents to the Guest anymore. Indicate
    // we handled this only if it's a non-resent event.
    return gesture_event.resending_plugin_id == browser_plugin_instance_id_
               ? blink::WebInputEventResult::kNotHandled
               : blink::WebInputEventResult::kHandledApplication;
  }

  if (event.GetType() == blink::WebInputEvent::kContextMenu)
    return blink::WebInputEventResult::kHandledSuppressed;

  if (blink::WebInputEvent::IsKeyboardEventType(event.GetType()) &&
      !edit_commands_.empty()) {
    BrowserPluginManager::Get()->Send(
        new BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent(
            browser_plugin_instance_id_,
            edit_commands_));
    edit_commands_.clear();
  }

  BrowserPluginManager::Get()->Send(
      new BrowserPluginHostMsg_HandleInputEvent(browser_plugin_instance_id_,
                                                &event));
  GetWebCursorInfo(cursor_, &cursor_info);

  // Although we forward this event to the guest, we don't report it as consumed
  // since other targets of this event in Blink never get that chance either.
  if (event.GetType() == blink::WebInputEvent::kGestureFlingStart)
    return blink::WebInputEventResult::kNotHandled;

  return blink::WebInputEventResult::kHandledApplication;
}

bool BrowserPlugin::HandleDragStatusUpdate(blink::WebDragStatus drag_status,
                                           const blink::WebDragData& drag_data,
                                           blink::WebDragOperationsMask mask,
                                           const blink::WebFloatPoint& position,
                                           const blink::WebFloatPoint& screen) {
  if (guest_crashed_ || !attached())
    return false;
  BrowserPluginManager::Get()->Send(
      new BrowserPluginHostMsg_DragStatusUpdate(
        browser_plugin_instance_id_,
        drag_status,
        DropDataBuilder::Build(drag_data),
        mask,
        position));
  return true;
}

void BrowserPlugin::DidReceiveResponse(const blink::WebURLResponse& response) {}

void BrowserPlugin::DidReceiveData(const char* data, int data_length) {
  if (delegate_)
    delegate_->PluginDidReceiveData(data, data_length);
}

void BrowserPlugin::DidFinishLoading() {
  if (delegate_)
    delegate_->PluginDidFinishLoading();
}

void BrowserPlugin::DidFailLoading(const blink::WebURLError& error) {}

bool BrowserPlugin::ExecuteEditCommand(const blink::WebString& name) {
  BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_ExecuteEditCommand(
      browser_plugin_instance_id_, name.Utf8()));

  // BrowserPlugin swallows edit commands.
  return true;
}

bool BrowserPlugin::ExecuteEditCommand(const blink::WebString& name,
                                       const blink::WebString& value) {
  edit_commands_.push_back(EditCommand(name.Utf8(), value.Utf8()));
  // BrowserPlugin swallows edit commands.
  return true;
}

bool BrowserPlugin::SetComposition(
    const blink::WebString& text,
    const blink::WebVector<blink::WebImeTextSpan>& ime_text_spans,
    const blink::WebRange& replacementRange,
    int selectionStart,
    int selectionEnd) {
  if (!attached())
    return false;

  BrowserPluginHostMsg_SetComposition_Params params;
  params.text = text.Utf16();
  for (size_t i = 0; i < ime_text_spans.size(); ++i) {
    params.ime_text_spans.push_back(ime_text_spans[i]);
  }

  params.replacement_range =
      replacementRange.IsNull()
          ? gfx::Range::InvalidRange()
          : gfx::Range(static_cast<uint32_t>(replacementRange.StartOffset()),
                       static_cast<uint32_t>(replacementRange.EndOffset()));
  params.selection_start = selectionStart;
  params.selection_end = selectionEnd;

  BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_ImeSetComposition(
      browser_plugin_instance_id_, params));
  // TODO(kochi): This assumes the IPC handling always succeeds.
  return true;
}

bool BrowserPlugin::CommitText(
    const blink::WebString& text,
    const blink::WebVector<blink::WebImeTextSpan>& ime_text_spans,
    const blink::WebRange& replacementRange,
    int relative_cursor_pos) {
  if (!attached())
    return false;

  std::vector<blink::WebImeTextSpan> std_ime_text_spans;
  for (size_t i = 0; i < ime_text_spans.size(); ++i) {
    std_ime_text_spans.push_back(ime_text_spans[i]);
  }
  gfx::Range replacement_range =
      replacementRange.IsNull()
          ? gfx::Range::InvalidRange()
          : gfx::Range(static_cast<uint32_t>(replacementRange.StartOffset()),
                       static_cast<uint32_t>(replacementRange.EndOffset()));

  BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_ImeCommitText(
      browser_plugin_instance_id_, text.Utf16(), std_ime_text_spans,
      replacement_range, relative_cursor_pos));
  // TODO(kochi): This assumes the IPC handling always succeeds.
  return true;
}

bool BrowserPlugin::FinishComposingText(
    blink::WebInputMethodController::ConfirmCompositionBehavior
        selection_behavior) {
  if (!attached())
    return false;
  bool keep_selection =
      (selection_behavior == blink::WebInputMethodController::kKeepSelection);
  BrowserPluginManager::Get()->Send(
      new BrowserPluginHostMsg_ImeFinishComposingText(
          browser_plugin_instance_id_, keep_selection));
  // TODO(kochi): This assumes the IPC handling always succeeds.
  return true;
}

void BrowserPlugin::ExtendSelectionAndDelete(int before, int after) {
  if (!attached())
    return;
  BrowserPluginManager::Get()->Send(
      new BrowserPluginHostMsg_ExtendSelectionAndDelete(
          browser_plugin_instance_id_,
          before,
          after));
}

void BrowserPlugin::OnLockMouseACK(bool succeeded) {
  mouse_locked_ = succeeded;
  BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_LockMouse_ACK(
      browser_plugin_instance_id_,
      succeeded));
}

void BrowserPlugin::OnMouseLockLost() {
  mouse_locked_ = false;
  BrowserPluginManager::Get()->Send(new BrowserPluginHostMsg_UnlockMouse_ACK(
      browser_plugin_instance_id_));
}

bool BrowserPlugin::HandleMouseLockedInputEvent(
    const blink::WebMouseEvent& event) {
  BrowserPluginManager::Get()->Send(
      new BrowserPluginHostMsg_HandleInputEvent(browser_plugin_instance_id_,
                                                &event));
  return true;
}

#if defined(USE_AURA)
void BrowserPlugin::OnMusEmbeddedFrameSurfaceChanged(
    const viz::SurfaceInfo& surface_info) {
  if (!attached_)
    return;

  compositing_helper_->SetFallbackSurfaceId(surface_info.id(),
                                            screen_space_rect().size());
}

void BrowserPlugin::OnMusEmbeddedFrameSinkIdAllocated(
    const viz::FrameSinkId& frame_sink_id) {
  // RendererWindowTreeClient should only call this when mus is hosting viz.
  DCHECK(base::FeatureList::IsEnabled(features::kMash));
  OnGuestReady(browser_plugin_instance_id_, frame_sink_id);
}
#endif

cc::Layer* BrowserPlugin::GetLayer() {
  return embedded_layer_.get();
}

void BrowserPlugin::SetLayer(scoped_refptr<cc::Layer> layer,
                             bool prevent_contents_opaque_changes) {
  if (container_)
    container_->SetCcLayer(layer.get(), prevent_contents_opaque_changes);
  embedded_layer_ = std::move(layer);
}

SkBitmap* BrowserPlugin::GetSadPageBitmap() {
  return GetContentClient()->renderer()->GetSadWebViewBitmap();
}

}  // namespace content
