/*
 * Copyright (C) 2009 Google Inc. All rights reserved.
 * Copyright (C) 2014 Opera Software ASA. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"

#include "build/build_config.h"
#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_drag_data.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url_error.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_dom_message_event.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_local_frame_client.h"
#include "third_party/blink/public/web/web_plugin.h"
#include "third_party/blink/public/web/web_print_params.h"
#include "third_party/blink/public/web/web_print_preset_options.h"
#include "third_party/blink/public/web/web_view_client.h"
#include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h"
#include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_element.h"
#include "third_party/blink/renderer/core/clipboard/clipboard_utilities.h"
#include "third_party/blink/renderer/core/clipboard/data_object.h"
#include "third_party/blink/renderer/core/clipboard/data_transfer.h"
#include "third_party/blink/renderer/core/clipboard/system_clipboard.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
#include "third_party/blink/renderer/core/events/drag_event.h"
#include "third_party/blink/renderer/core/events/gesture_event.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
#include "third_party/blink/renderer/core/events/mouse_event.h"
#include "third_party/blink/renderer/core/events/progress_event.h"
#include "third_party/blink/renderer/core/events/resource_progress_event.h"
#include "third_party/blink/renderer/core/events/touch_event.h"
#include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
#include "third_party/blink/renderer/core/events/wheel_event.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/exported/web_document_loader_impl.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/event_handler_registry.h"
#include "third_party/blink/renderer/core/frame/find_in_page.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
#include "third_party/blink/renderer/core/html/forms/html_form_element.h"
#include "third_party/blink/renderer/core/html/html_plugin_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/pointer_lock_controller.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/script/classic_script.h"
#include "third_party/blink/renderer/core/scroll/scroll_animator_base.h"
#include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
#include "third_party/blink/renderer/platform/exported/wrapped_resource_response.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/keyboard_codes.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-blink.h"

namespace blink {

namespace {

#if defined(OS_MAC)
const WebInputEvent::Modifiers kEditingModifier = WebInputEvent::kMetaKey;
#else
const WebInputEvent::Modifiers kEditingModifier = WebInputEvent::kControlKey;
#endif

}  // namespace

class WebPluginContainerImpl::MouseLockLostListener final
    : public NativeEventListener {
 public:
  explicit MouseLockLostListener(WebPluginContainerImpl* plugin_container)
      : plugin_container_(plugin_container) {}

  void Disconnect() { plugin_container_ = nullptr; }

  void Invoke(ExecutionContext*, Event*) override {
    if (!plugin_container_)
      return;
    plugin_container_->MaybeLostMouseLock();
  }

  void Trace(Visitor* visitor) const override {
    visitor->Trace(plugin_container_);
    NativeEventListener::Trace(visitor);
  }

 private:
  Member<WebPluginContainerImpl> plugin_container_;
};

// Public methods --------------------------------------------------------------

void WebPluginContainerImpl::AttachToLayout() {
  DCHECK(!IsAttached());
  SetAttached(true);
  SetParentVisible(true);
}

void WebPluginContainerImpl::DetachFromLayout() {
  DCHECK(IsAttached());
  SetParentVisible(false);
  SetAttached(false);
}

void WebPluginContainerImpl::UpdateAllLifecyclePhases() {
  if (!web_plugin_)
    return;

  web_plugin_->UpdateAllLifecyclePhases(DocumentUpdateReason::kPlugin);
}

void WebPluginContainerImpl::Paint(GraphicsContext& context,
                                   const GlobalPaintFlags,
                                   const CullRect& cull_rect,
                                   const IntSize& paint_offset) const {
  // Don't paint anything if the plugin doesn't intersect.
  if (!cull_rect.Intersects(FrameRect()))
    return;

  IntRect visual_rect = FrameRect();
  visual_rect.Move(paint_offset);

  if (WantsWheelEvents()) {
    context.GetPaintController().RecordScrollHitTestData(
        *GetLayoutEmbeddedContent(), DisplayItem::kPluginScrollHitTest, nullptr,
        visual_rect);
  }

  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && layer_) {
    layer_->SetBounds(gfx::Size(Size()));
    layer_->SetIsDrawable(true);
    layer_->SetHitTestable(true);
    auto offset = RoundedIntPoint(
        GetLayoutEmbeddedContent()->ReplacedContentRect().offset);
    // When compositing is after paint, composited plugins should have their
    // layers inserted rather than invoking WebPlugin::paint.
    RecordForeignLayer(context, *element_->GetLayoutObject(),
                       DisplayItem::kForeignLayerPlugin, layer_, offset);
    return;
  }

  if (DrawingRecorder::UseCachedDrawingIfPossible(
          context, *element_->GetLayoutObject(), DisplayItem::kWebPlugin))
    return;

  DrawingRecorder recorder(context, *element_->GetLayoutObject(),
                           DisplayItem::kWebPlugin, visual_rect);
  context.Save();

  // The plugin is positioned in the root frame's coordinates, so it needs to
  // be painted in them too.
  FloatPoint origin(ParentFrameView()->ConvertToRootFrame(IntPoint()));
  origin.Move(-paint_offset);
  context.Translate(-origin.X(), -origin.Y());

  cc::PaintCanvas* canvas = context.Canvas();

  IntRect window_rect = ParentFrameView()->ConvertToRootFrame(cull_rect.Rect());
  web_plugin_->Paint(canvas, window_rect);

  context.Restore();
}

void WebPluginContainerImpl::UpdateGeometry() {
  if (LayoutEmbeddedContent* layout = GetLayoutEmbeddedContent())
    layout->UpdateGeometry(*this);
}

void WebPluginContainerImpl::InvalidateRect(const IntRect& rect) {
  // InvalidateRect can be called from Dispose when this plugin is no longer
  // attached.  In this case, we return immediately.
  if (!IsAttached())
    return;

  auto* layout_object = To<LayoutBox>(element_->GetLayoutObject());
  if (!layout_object)
    return;

  IntRect dirty_rect = rect;
  dirty_rect.Move(
      (layout_object->BorderLeft() + layout_object->PaddingLeft()).ToInt(),
      (layout_object->BorderTop() + layout_object->PaddingTop()).ToInt());

  layout_object->InvalidatePaintRectangle(PhysicalRect(dirty_rect));
}

void WebPluginContainerImpl::SetFocused(bool focused,
                                        mojom::blink::FocusType focus_type) {
  web_plugin_->UpdateFocus(focused, focus_type);
}

bool WebPluginContainerImpl::IsErrorplaceholder() {
  if (!web_plugin_)
    return false;
  return web_plugin_->IsErrorPlaceholder();
}

void WebPluginContainerImpl::Show() {
  SetSelfVisible(true);
  web_plugin_->UpdateVisibility(true);
}

void WebPluginContainerImpl::Hide() {
  SetSelfVisible(false);
  web_plugin_->UpdateVisibility(false);
}

void WebPluginContainerImpl::HandleEvent(Event& event) {
  // The events we pass are defined at:
  //    http://devedge-temp.mozilla.org/library/manuals/2002/plugin/1.0/structures5.html#1000000
  // Don't take the documentation as truth, however.  There are many cases
  // where mozilla behaves differently than the spec.
  if (auto* mouse_event = DynamicTo<MouseEvent>(event))
    HandleMouseEvent(*mouse_event);
  else if (auto* wheel_event = DynamicTo<WheelEvent>(event))
    HandleWheelEvent(*wheel_event);
  else if (auto* keyboard_event = DynamicTo<KeyboardEvent>(event))
    HandleKeyboardEvent(*keyboard_event);
  else if (auto* touch_event = DynamicTo<TouchEvent>(event))
    HandleTouchEvent(*touch_event);
  else if (auto* gesture_event = DynamicTo<GestureEvent>(event))
    HandleGestureEvent(*gesture_event);
  else if (IsA<DragEvent>(event) && web_plugin_->CanProcessDrag())
    HandleDragEvent(To<DragEvent>(event));

  // FIXME: it would be cleaner if EmbeddedContentView::HandleEvent returned
  // true/false and HTMLPluginElement called SetDefaultHandled or
  // DefaultEventHandler.
  if (!event.DefaultHandled())
    element_->Node::DefaultEventHandler(event);
}

void WebPluginContainerImpl::EventListenersRemoved() {
  // We're no longer registered to receive touch events, so don't try to remove
  // the touch event handlers in our destructor.
  touch_event_request_type_ = kTouchEventRequestTypeNone;
}

void WebPluginContainerImpl::ParentVisibleChanged() {
  // We override this function to make sure that geometry updates are sent
  // over to the plugin. For e.g. when a plugin is instantiated it does not
  // have a valid parent. As a result the first geometry update is ignored. This
  // function is called when the plugin eventually gets a parent.
  if (web_plugin_ && IsSelfVisible())
    web_plugin_->UpdateVisibility(IsVisible());
}

void WebPluginContainerImpl::SetPlugin(WebPlugin* plugin) {
  if (plugin == web_plugin_)
    return;

  element_->ResetInstance();
  web_plugin_ = plugin;
}

void WebPluginContainerImpl::UsePluginAsFindHandler() {
  WebLocalFrameImpl* frame =
      WebLocalFrameImpl::FromFrame(element_->GetDocument().GetFrame());
  if (!frame)
    return;
  frame->GetFindInPage()->SetPluginFindHandler(this);
}

void WebPluginContainerImpl::ReportFindInPageMatchCount(int identifier,
                                                        int total,
                                                        bool final_update) {
  WebLocalFrameImpl* frame =
      WebLocalFrameImpl::FromFrame(element_->GetDocument().GetFrame());
  if (!frame)
    return;
  frame->GetFindInPage()->ReportFindInPageMatchCount(identifier, total,
                                                     final_update);
}

void WebPluginContainerImpl::ReportFindInPageSelection(int identifier,
                                                       int index) {
  WebLocalFrameImpl* frame =
      WebLocalFrameImpl::FromFrame(element_->GetDocument().GetFrame());
  if (!frame)
    return;
  frame->GetFindInPage()->ReportFindInPageSelection(
      identifier, index, gfx::Rect(), false /* final_update */);
}

float WebPluginContainerImpl::DeviceScaleFactor() {
  Page* page = element_->GetDocument().GetPage();
  if (!page)
    return 1.0;
  return page->DeviceScaleFactorDeprecated();
}

float WebPluginContainerImpl::PageScaleFactor() {
  Page* page = element_->GetDocument().GetPage();
  if (!page)
    return 1.0;
  return page->PageScaleFactor();
}

float WebPluginContainerImpl::PageZoomFactor() {
  LocalFrame* frame = element_->GetDocument().GetFrame();
  if (!frame)
    return 1.0;
  return frame->PageZoomFactor();
}

void WebPluginContainerImpl::SetCcLayer(cc::Layer* new_layer) {
  if (layer_ == new_layer)
    return;
  layer_ = new_layer;
  if (element_)
    element_->SetNeedsCompositingUpdate();
}

void WebPluginContainerImpl::RequestFullscreen() {
  Fullscreen::RequestFullscreen(*element_);
}

bool WebPluginContainerImpl::IsFullscreenElement() const {
  return Fullscreen::IsFullscreenElement(*element_);
}

void WebPluginContainerImpl::CancelFullscreen() {
  Fullscreen::FullyExitFullscreen(element_->GetDocument());
}

bool WebPluginContainerImpl::IsMouseLocked() {
  return element_->GetDocument().PointerLockElement() == element_;
}

bool WebPluginContainerImpl::LockMouse(bool request_unadjusted_movement) {
  if (Page* page = element_->GetDocument().GetPage()) {
    bool res = page->GetPointerLockController().RequestPointerLock(
        element_, WTF::Bind(&WebPluginContainerImpl::HandleLockMouseResult,
                            WrapWeakPersistent(this)));
    if (res) {
      mouse_lock_lost_listener_ =
          MakeGarbageCollected<MouseLockLostListener>(this);
      element_->GetDocument().addEventListener(
          event_type_names::kPointerlockchange, mouse_lock_lost_listener_,
          false);
    }
    return res;
  }
  return false;
}

void WebPluginContainerImpl::UnlockMouse() {
  element_->GetDocument().exitPointerLock();
}

void WebPluginContainerImpl::HandleLockMouseResult(
    mojom::blink::PointerLockResult result) {
  web_plugin_->DidReceiveMouseLockResult(
      result == mojom::blink::PointerLockResult::kSuccess);
}

void WebPluginContainerImpl::MaybeLostMouseLock() {
  if (!IsMouseLocked()) {
    if (mouse_lock_lost_listener_) {
      mouse_lock_lost_listener_->Disconnect();
      element_->GetDocument().removeEventListener(
          event_type_names::kPointerlockchange, mouse_lock_lost_listener_,
          false);
      mouse_lock_lost_listener_ = nullptr;
    }
    web_plugin_->DidLoseMouseLock();
  }
}

bool WebPluginContainerImpl::SupportsPaginatedPrint() const {
  return web_plugin_->SupportsPaginatedPrint();
}

bool WebPluginContainerImpl::GetPrintPresetOptionsFromDocument(
    WebPrintPresetOptions* preset_options) const {
  return web_plugin_->GetPrintPresetOptionsFromDocument(preset_options);
}

int WebPluginContainerImpl::PrintBegin(
    const WebPrintParams& print_params) const {
  return web_plugin_->PrintBegin(print_params);
}

void WebPluginContainerImpl::PrintPage(int page_number, GraphicsContext& gc) {
  if (DrawingRecorder::UseCachedDrawingIfPossible(
          gc, *element_->GetLayoutObject(), DisplayItem::kWebPlugin))
    return;

  DrawingRecorder recorder(gc, *element_->GetLayoutObject(),
                           DisplayItem::kWebPlugin, FrameRect());
  gc.Save();

  cc::PaintCanvas* canvas = gc.Canvas();
  web_plugin_->PrintPage(page_number, canvas);
  gc.Restore();
}

void WebPluginContainerImpl::PrintEnd() {
  web_plugin_->PrintEnd();
}

void WebPluginContainerImpl::Copy() {
  if (!web_plugin_->HasSelection())
    return;

  LocalFrame* frame = element_->GetDocument().GetFrame();
  frame->GetSystemClipboard()->WriteHTML(web_plugin_->SelectionAsMarkup(),
                                         KURL());
  String text = web_plugin_->SelectionAsText();
  ReplaceNBSPWithSpace(text);
  frame->GetSystemClipboard()->WritePlainText(text);
  frame->GetSystemClipboard()->CommitWrite();
}

bool WebPluginContainerImpl::ExecuteEditCommand(const WebString& name) {
  return ExecuteEditCommand(name, WebString());
}

bool WebPluginContainerImpl::ExecuteEditCommand(const WebString& name,
                                                const WebString& value) {
  DCHECK(value.IsEmpty());

  // If the clipboard contains something other than text (e.g. an image),
  // ReadPlainText() returns an empty string. The empty string is then pasted,
  // replacing any selected text. This behavior is consistent with that of HTML
  // text form fields.
  String text;
  if (name == "Paste" || name == "PasteAndMatchStyle") {
    LocalFrame* frame = element_->GetDocument().GetFrame();
    text = frame->GetSystemClipboard()->ReadPlainText();
  }

  // If copying or cutting, make sure to copy the plugin text to the clipboard
  // before executing the command.
  if (name == "Copy" || (name == "Cut" && web_plugin_->CanEditText()))
    Copy();

  return web_plugin_->ExecuteEditCommand(name, text);
}

// static
bool WebPluginContainerImpl::SupportsCommand(const WebString& name) {
  return name == "Copy" || name == "Cut" || name == "Paste" ||
         name == "PasteAndMatchStyle" || name == "SelectAll" ||
         name == "Undo" || name == "Redo";
}

WebElement WebPluginContainerImpl::GetElement() {
  return WebElement(element_);
}

WebDocument WebPluginContainerImpl::GetDocument() {
  return WebDocument(&element_->GetDocument());
}

void WebPluginContainerImpl::DispatchProgressEvent(const WebString& type,
                                                   bool length_computable,
                                                   uint64_t loaded,
                                                   uint64_t total,
                                                   const WebString& url) {
  ProgressEvent* event;
  if (url.IsEmpty()) {
    event = ProgressEvent::Create(type, length_computable, loaded, total);
  } else {
    event = MakeGarbageCollected<ResourceProgressEvent>(type, length_computable,
                                                        loaded, total, url);
  }
  element_->DispatchEvent(*event);
}

void WebPluginContainerImpl::EnqueueMessageEvent(
    const WebDOMMessageEvent& event) {
  if (!element_->GetExecutionContext())
    return;
  element_->EnqueueEvent(*event, TaskType::kInternalDefault);
}

void WebPluginContainerImpl::Invalidate() {
  InvalidateRect(IntRect(0, 0, Size().Width(), Size().Height()));
}

void WebPluginContainerImpl::InvalidateRect(const gfx::Rect& rect) {
  InvalidateRect(static_cast<IntRect>(rect));
}

void WebPluginContainerImpl::ScheduleAnimation() {
  if (auto* frame_view = element_->GetDocument().View())
    frame_view->ScheduleAnimation();
}

void WebPluginContainerImpl::ReportGeometry() {
  // Ignore when SetFrameRect/ReportGeometry is called from
  // UpdateOnEmbeddedContentViewChange before plugin is attached.
  if (!IsAttached())
    return;

  IntRect window_rect, clip_rect, unobscured_rect;
  CalculateGeometry(window_rect, clip_rect, unobscured_rect);
  web_plugin_->UpdateGeometry(window_rect, clip_rect, unobscured_rect,
                              IsSelfVisible());
}

v8::Local<v8::Object> WebPluginContainerImpl::V8ObjectForElement() {
  ExecutionContext* context = element_->GetExecutionContext();
  if (!context || !context->CanExecuteScripts(kNotAboutToExecuteScript))
    return v8::Local<v8::Object>();

  ScriptState* script_state =
      ToScriptState(context, DOMWrapperWorld::MainWorld());
  if (!script_state)
    return v8::Local<v8::Object>();

  v8::Local<v8::Value> v8value =
      ToV8(element_.Get(), script_state->GetContext()->Global(),
           script_state->GetIsolate());
  if (v8value.IsEmpty())
    return v8::Local<v8::Object>();
  DCHECK(v8value->IsObject());

  return v8::Local<v8::Object>::Cast(v8value);
}

void WebPluginContainerImpl::LoadFrameRequest(const WebURLRequest& request,
                                              const WebString& target) {
  LocalDOMWindow* window = element_->GetDocument().domWindow();
  if (!window)
    return;

  FrameLoadRequest frame_request(window, request.ToResourceRequest());
  Frame* target_frame =
      window->GetFrame()
          ->Tree()
          .FindOrCreateFrameForNavigation(frame_request, target)
          .frame;
  if (target_frame)
    target_frame->Navigate(frame_request, WebFrameLoadType::kStandard);
}

bool WebPluginContainerImpl::IsRectTopmost(const gfx::Rect& rect) {
  // Disallow access to the frame during Dispose(), because it is not guaranteed
  // to be valid memory once this object has started disposal. In particular,
  // we might be being disposed because the frame has already be deleted and
  // then something else dropped the
  // last reference to the this object.
  if (!IsAttached() || !element_)
    return false;

  LocalFrame* frame = element_->GetDocument().GetFrame();
  if (!frame)
    return false;

  IntRect frame_rect(rect);
  frame_rect.MoveBy(Location());
  HitTestLocation location((PhysicalRect(frame_rect)));
  HitTestResult result = frame->GetEventHandler().HitTestResultAtLocation(
      location, HitTestRequest::kReadOnly | HitTestRequest::kActive |
                    HitTestRequest::kListBased);
  const HitTestResult::NodeSet& nodes = result.ListBasedTestResult();
  if (nodes.size() != 1)
    return false;
  return nodes.front().Get() == element_;
}

void WebPluginContainerImpl::RequestTouchEventType(
    TouchEventRequestType request_type) {
  if (touch_event_request_type_ == request_type || !element_)
    return;

  if (auto* frame = element_->GetDocument().GetFrame()) {
    EventHandlerRegistry& registry = frame->GetEventHandlerRegistry();
    if (request_type == kTouchEventRequestTypeRawLowLatency) {
      if (touch_event_request_type_ != kTouchEventRequestTypeNone) {
        registry.DidRemoveEventHandler(
            *element_, EventHandlerRegistry::kTouchStartOrMoveEventBlocking);
      }
      registry.DidAddEventHandler(
          *element_,
          EventHandlerRegistry::kTouchStartOrMoveEventBlockingLowLatency);
    } else if (request_type != kTouchEventRequestTypeNone) {
      if (touch_event_request_type_ == kTouchEventRequestTypeRawLowLatency) {
        registry.DidRemoveEventHandler(
            *element_,
            EventHandlerRegistry::kTouchStartOrMoveEventBlockingLowLatency);
      }
      if (touch_event_request_type_ == kTouchEventRequestTypeNone ||
          touch_event_request_type_ == kTouchEventRequestTypeRawLowLatency) {
        registry.DidAddEventHandler(
            *element_, EventHandlerRegistry::kTouchStartOrMoveEventBlocking);
      }
    } else if (touch_event_request_type_ != kTouchEventRequestTypeNone) {
      registry.DidRemoveEventHandler(
          *element_,
          touch_event_request_type_ == kTouchEventRequestTypeRawLowLatency
              ? EventHandlerRegistry::kTouchStartOrMoveEventBlockingLowLatency
              : EventHandlerRegistry::kTouchStartOrMoveEventBlocking);
    }
  }
  touch_event_request_type_ = request_type;
}

void WebPluginContainerImpl::SetWantsWheelEvents(bool wants_wheel_events) {
  if (wants_wheel_events_ == wants_wheel_events)
    return;

  if (auto* frame = element_->GetDocument().GetFrame()) {
    EventHandlerRegistry& registry = frame->GetEventHandlerRegistry();
    if (wants_wheel_events) {
      registry.DidAddEventHandler(*element_,
                                  EventHandlerRegistry::kWheelEventBlocking);
    } else {
      registry.DidRemoveEventHandler(*element_,
                                     EventHandlerRegistry::kWheelEventBlocking);
    }
  }

  wants_wheel_events_ = wants_wheel_events;

  if (IsAttached()) {
    // Scroll hit test data depend on wheel events. They are painted in the
    // background phase.
    GetLayoutEmbeddedContent()->SetBackgroundNeedsFullPaintInvalidation();
  }
}

gfx::Point WebPluginContainerImpl::RootFrameToLocalPoint(
    const gfx::Point& point_in_root_frame) {
  gfx::Point point_in_content =
      ParentFrameView()->ConvertFromRootFrame(IntPoint(point_in_root_frame));
  return RoundedIntPoint(element_->GetLayoutObject()->AbsoluteToLocalPoint(
      PhysicalOffset(point_in_content)));
}

gfx::Point WebPluginContainerImpl::LocalToRootFramePoint(
    const gfx::Point& point_in_local) {
  IntPoint absolute_point =
      RoundedIntPoint(element_->GetLayoutObject()->LocalToAbsolutePoint(
          PhysicalOffset(point_in_local)));
  return ParentFrameView()->ConvertToRootFrame(absolute_point);
}

bool WebPluginContainerImpl::WasTargetForLastMouseEvent() {
  auto* frame = element_->GetDocument().GetFrame();
  if (!frame)
    return false;
  return frame->GetEventHandler().GetElementUnderMouse() == element_;
}

void WebPluginContainerImpl::DidReceiveResponse(
    const ResourceResponse& response) {
  // Make sure that the plugin receives window geometry before data, or else
  // plugins misbehave.
  ReportGeometry();

  WrappedResourceResponse url_response(response);
  web_plugin_->DidReceiveResponse(url_response);
}

void WebPluginContainerImpl::DidReceiveData(const char* data,
                                            size_t data_length) {
  web_plugin_->DidReceiveData(data, data_length);
}

void WebPluginContainerImpl::DidFinishLoading() {
  web_plugin_->DidFinishLoading();
}

void WebPluginContainerImpl::DidFailLoading(const ResourceError& error) {
  web_plugin_->DidFailLoading(WebURLError(error));
}

cc::Layer* WebPluginContainerImpl::CcLayer() const {
  return layer_;
}

v8::Local<v8::Object> WebPluginContainerImpl::ScriptableObject(
    v8::Isolate* isolate) {
  // With Oilpan, on plugin element detach dispose() will be called to safely
  // clear out references, including the pre-emptive destruction of the plugin.
  //
  // It clearly has no scriptable object if in such a disposed state.
  if (!web_plugin_)
    return v8::Local<v8::Object>();

  v8::Local<v8::Object> object = web_plugin_->V8ScriptableObject(isolate);

  // If the plugin has been destroyed and the reference on the stack is the
  // only one left, then don't return the scriptable object.
  if (!web_plugin_)
    return v8::Local<v8::Object>();

  return object;
}

bool WebPluginContainerImpl::SupportsKeyboardFocus() const {
  return web_plugin_->SupportsKeyboardFocus();
}

bool WebPluginContainerImpl::SupportsInputMethod() const {
  return web_plugin_->SupportsInputMethod();
}

bool WebPluginContainerImpl::CanProcessDrag() const {
  return web_plugin_->CanProcessDrag();
}

bool WebPluginContainerImpl::WantsWheelEvents() const {
  return wants_wheel_events_;
}

// Private methods -------------------------------------------------------------

WebPluginContainerImpl::WebPluginContainerImpl(HTMLPlugInElement& element,
                                               WebPlugin* web_plugin)
    : EmbeddedContentView(IntRect()),
      element_(element),
      web_plugin_(web_plugin),
      layer_(nullptr),
      touch_event_request_type_(kTouchEventRequestTypeNone),
      wants_wheel_events_(false) {}

WebPluginContainerImpl::~WebPluginContainerImpl() {
  // The plugin container must have been disposed of by now.
  DCHECK(!web_plugin_);
}

LocalFrameView* WebPluginContainerImpl::ParentFrameView() const {
  DCHECK(IsAttached());
  return element_->GetDocument().GetFrame()->View();
}

LayoutEmbeddedContent* WebPluginContainerImpl::GetLayoutEmbeddedContent()
    const {
  return element_->GetLayoutEmbeddedContent();
}

void WebPluginContainerImpl::Dispose() {
  SetAttached(false);

  RequestTouchEventType(kTouchEventRequestTypeNone);
  SetWantsWheelEvents(false);

  if (WebLocalFrameImpl* frame =
          WebLocalFrameImpl::FromFrame(element_->GetDocument().GetFrame())) {
    if (frame->GetFindInPage()->PluginFindHandler() == this)
      frame->GetFindInPage()->SetPluginFindHandler(nullptr);
  }

  if (web_plugin_) {
    CHECK(web_plugin_->Container() == this);
    web_plugin_->Destroy();
    web_plugin_ = nullptr;
  }

  layer_ = nullptr;
}

void WebPluginContainerImpl::SetFrameRect(const IntRect& rect) {
  IntRect old_rect(FrameRect());
  EmbeddedContentView::SetFrameRect(rect);
  // We need to report every time SetFrameRect is called, even if there is no
  // change (if there is a change, FrameRectsChanged will do the reporting).
  if (old_rect == FrameRect())
    PropagateFrameRects();
}

void WebPluginContainerImpl::Trace(Visitor* visitor) const {
  visitor->Trace(element_);
  visitor->Trace(mouse_lock_lost_listener_);
}

void WebPluginContainerImpl::HandleMouseEvent(MouseEvent& event) {
  // We cache the parent LocalFrameView here as the plugin widget could be
  // deleted in the call to HandleEvent. See http://b/issue?id=1362948
  LocalFrameView* parent = ParentFrameView();

  // TODO(dtapuska): Move WebMouseEventBuilder into the anonymous namespace
  // in this class.
  WebMouseEventBuilder transformed_event(parent, element_->GetLayoutObject(),
                                         event);
  if (transformed_event.GetType() == WebInputEvent::Type::kUndefined)
    return;

  if (event.type() == event_type_names::kMousedown)
    FocusPlugin();

  ui::Cursor cursor(ui::mojom::blink::CursorType::kPointer);
  if (web_plugin_ &&
      web_plugin_->HandleInputEvent(
          WebCoalescedInputEvent(transformed_event, ui::LatencyInfo()),
          &cursor) != WebInputEventResult::kNotHandled)
    event.SetDefaultHandled();

  // A windowless plugin can change the cursor in response to a mouse move
  // event.  We need to reflect the changed cursor in the frame view as the
  // mouse is moved in the boundaries of the windowless plugin.
  Page* page = parent->GetFrame().GetPage();
  if (!page)
    return;
  page->GetChromeClient().SetCursorForPlugin(
      cursor, &parent->GetFrame().LocalFrameRoot());
}

void WebPluginContainerImpl::HandleDragEvent(MouseEvent& event) {
  DCHECK(IsA<DragEvent>(event));

  WebDragStatus drag_status = kWebDragStatusUnknown;
  if (event.type() == event_type_names::kDragenter)
    drag_status = kWebDragStatusEnter;
  else if (event.type() == event_type_names::kDragleave)
    drag_status = kWebDragStatusLeave;
  else if (event.type() == event_type_names::kDragover)
    drag_status = kWebDragStatusOver;
  else if (event.type() == event_type_names::kDrop)
    drag_status = kWebDragStatusDrop;

  if (drag_status == kWebDragStatusUnknown)
    return;

  DataTransfer* data_transfer = event.getDataTransfer();
  WebDragData drag_data = data_transfer->GetDataObject()->ToWebDragData();
  DragOperationsMask drag_operation_mask = data_transfer->SourceOperation();
  gfx::PointF drag_screen_location(event.screenX(), event.screenY());
  IntPoint location(Location());
  gfx::PointF drag_location(event.AbsoluteLocation().X() - location.X(),
                            event.AbsoluteLocation().Y() - location.Y());

  web_plugin_->HandleDragStatusUpdate(drag_status, drag_data,
                                      drag_operation_mask, drag_location,
                                      drag_screen_location);
}

void WebPluginContainerImpl::HandleWheelEvent(WheelEvent& event) {
  FloatPoint absolute_location =
      FloatPoint(event.NativeEvent().PositionInRootFrame());

  // Translate the root frame position to content coordinates.
  absolute_location =
      ParentFrameView()->ConvertFromRootFrame(absolute_location);

  FloatPoint local_point =
      element_->GetLayoutObject()->AbsoluteToLocalFloatPoint(absolute_location);
  WebMouseWheelEvent translated_event = event.NativeEvent().FlattenTransform();
  translated_event.SetPositionInWidget(local_point.X(), local_point.Y());

  ui::Cursor dummy_cursor;
  if (web_plugin_->HandleInputEvent(
          WebCoalescedInputEvent(translated_event, ui::LatencyInfo()),
          &dummy_cursor) != WebInputEventResult::kNotHandled)
    event.SetDefaultHandled();
}

void WebPluginContainerImpl::HandleKeyboardEvent(KeyboardEvent& event) {
  WebKeyboardEventBuilder web_event(event);
  if (web_event.GetType() == WebInputEvent::Type::kUndefined)
    return;

  if (HandleCutCopyPasteKeyboardEvent(web_event)) {
    event.SetDefaultHandled();
    return;
  }

  ui::Cursor dummy_cursor;
  if (web_plugin_->HandleInputEvent(
          WebCoalescedInputEvent(web_event, ui::LatencyInfo()),
          &dummy_cursor) != WebInputEventResult::kNotHandled) {
    event.SetDefaultHandled();
  }
}

bool WebPluginContainerImpl::HandleCutCopyPasteKeyboardEvent(
    const WebKeyboardEvent& event) {
  if (event.GetType() != WebInputEvent::Type::kRawKeyDown &&
      event.GetType() != WebInputEvent::Type::kKeyDown) {
    return false;
  }

  int input_modifiers = event.GetModifiers() & WebInputEvent::kInputModifiers;
  if (input_modifiers == kEditingModifier) {
    // Only copy/cut if there's a selection, so that we only ever do
    // this for Pepper plugins that support copying/cutting.
    if (web_plugin_->HasSelection()) {
      if (event.windows_key_code == VKEY_C ||
          event.windows_key_code == VKEY_INSERT) {
        Copy();
        return true;
      }
      if (event.windows_key_code == VKEY_X)
        return ExecuteEditCommand("Cut", "");
    }
    // Ask the plugin if it can edit text before executing "Paste".
    if (event.windows_key_code == VKEY_V && web_plugin_->CanEditText())
      return ExecuteEditCommand("Paste", "");
    return false;
  }

  if (input_modifiers == WebInputEvent::kShiftKey) {
    // Alternate shortcuts for "Cut" and "Paste" are Shift + Delete and Shift +
    // Insert, respectively.
    if (event.windows_key_code == VKEY_DELETE && web_plugin_->HasSelection())
      return ExecuteEditCommand("Cut", "");
    if (event.windows_key_code == VKEY_INSERT && web_plugin_->CanEditText())
      return ExecuteEditCommand("Paste", "");
    return false;
  }

  // Invoke "PasteAndMatchStyle" using Ctrl + Shift + V to paste as plain
  // text.
  if (input_modifiers == (kEditingModifier | WebInputEvent::kShiftKey) &&
      event.windows_key_code == VKEY_V && web_plugin_->CanEditText()) {
    return ExecuteEditCommand("PasteAndMatchStyle", "");
  }
  return false;
}

WebTouchEvent WebPluginContainerImpl::TransformTouchEvent(
    const WebInputEvent& event) {
  DCHECK(blink::WebInputEvent::IsTouchEventType(event.GetType()));
  const WebTouchEvent* touch_event = static_cast<const WebTouchEvent*>(&event);
  WebTouchEvent transformed_event = touch_event->FlattenTransform();

  LocalFrameView* parent = ParentFrameView();
  for (unsigned i = 0; i < transformed_event.touches_length; ++i) {
    FloatPoint absolute_location =
        FloatPoint(transformed_event.touches[i].PositionInWidget());

    // Translate the root frame position to content coordinates.
    absolute_location = parent->ConvertFromRootFrame(absolute_location);

    FloatPoint local_point =
        element_->GetLayoutObject()->AbsoluteToLocalFloatPoint(
            absolute_location);
    transformed_event.touches[i].SetPositionInWidget(local_point);
  }
  return transformed_event;
}

WebCoalescedInputEvent WebPluginContainerImpl::TransformCoalescedTouchEvent(
    const WebCoalescedInputEvent& coalesced_event) {
  WebCoalescedInputEvent transformed_event(
      TransformTouchEvent(coalesced_event.Event()).Clone(), {}, {},
      coalesced_event.latency_info());
  for (size_t i = 0; i < coalesced_event.CoalescedEventSize(); ++i) {
    transformed_event.AddCoalescedEvent(
        TransformTouchEvent(coalesced_event.CoalescedEvent(i)));
  }
  for (size_t i = 0; i < coalesced_event.PredictedEventSize(); ++i) {
    transformed_event.AddPredictedEvent(
        TransformTouchEvent(coalesced_event.PredictedEvent(i)));
  }
  return transformed_event;
}

void WebPluginContainerImpl::HandleTouchEvent(TouchEvent& event) {
  switch (touch_event_request_type_) {
    case kTouchEventRequestTypeNone:
      return;
    case kTouchEventRequestTypeRaw:
    case kTouchEventRequestTypeRawLowLatency: {
      if (!event.NativeEvent())
        return;

      if (event.type() == event_type_names::kTouchstart)
        FocusPlugin();

      WebCoalescedInputEvent transformed_event =
          TransformCoalescedTouchEvent(*event.NativeEvent());

      ui::Cursor dummy_cursor;
      if (web_plugin_->HandleInputEvent(transformed_event, &dummy_cursor) !=
          WebInputEventResult::kNotHandled)
        event.SetDefaultHandled();
      // FIXME: Can a plugin change the cursor from a touch-event callback?
      return;
    }
    case kTouchEventRequestTypeSynthesizedMouse:
      SynthesizeMouseEventIfPossible(event);
      return;
  }
}

void WebPluginContainerImpl::HandleGestureEvent(GestureEvent& event) {
  if (event.NativeEvent().GetType() == WebInputEvent::Type::kUndefined)
    return;
  if (event.NativeEvent().GetType() == WebInputEvent::Type::kGestureTapDown)
    FocusPlugin();

  // Take a copy of the event and translate it into the coordinate
  // system of the plugin.
  WebGestureEvent translated_event = event.NativeEvent();
  gfx::PointF absolute_root_frame_location =
      event.NativeEvent().PositionInRootFrame();
  FloatPoint local_point =
      element_->GetLayoutObject()->AbsoluteToLocalFloatPoint(
          FloatPoint(absolute_root_frame_location));
  translated_event.FlattenTransform();
  translated_event.SetPositionInWidget(local_point);

  ui::Cursor dummy_cursor;
  if (web_plugin_->HandleInputEvent(
          WebCoalescedInputEvent(translated_event, ui::LatencyInfo()),
          &dummy_cursor) != WebInputEventResult::kNotHandled) {
    event.SetDefaultHandled();
    return;
  }

  // FIXME: Can a plugin change the cursor from a touch-event callback?
}

void WebPluginContainerImpl::SynthesizeMouseEventIfPossible(TouchEvent& event) {
  WebMouseEventBuilder web_event(ParentFrameView(), element_->GetLayoutObject(),
                                 event);
  if (web_event.GetType() == WebInputEvent::Type::kUndefined)
    return;

  ui::Cursor dummy_cursor;
  if (web_plugin_->HandleInputEvent(
          WebCoalescedInputEvent(web_event, ui::LatencyInfo()),
          &dummy_cursor) != WebInputEventResult::kNotHandled)
    event.SetDefaultHandled();
}

void WebPluginContainerImpl::FocusPlugin() {
  LocalFrame* frame = element_->GetDocument().GetFrame();
  DCHECK(IsAttached() && frame && frame->GetPage());
  frame->GetPage()->GetFocusController().SetFocusedElement(element_, frame);
}

void WebPluginContainerImpl::ComputeClipRectsForPlugin(
    const HTMLFrameOwnerElement* owner_element,
    IntRect& window_rect,
    IntRect& clipped_local_rect,
    IntRect& unclipped_int_local_rect) const {
  DCHECK(owner_element);

  if (!owner_element->GetLayoutObject()) {
    clipped_local_rect = IntRect();
    unclipped_int_local_rect = IntRect();
    return;
  }

  LayoutView* root_view = element_->GetDocument().View()->GetLayoutView();
  while (root_view->GetFrame()->OwnerLayoutObject())
    root_view = root_view->GetFrame()->OwnerLayoutObject()->View();

  auto* box = To<LayoutBox>(owner_element->GetLayoutObject());

  // Note: FrameRect() for this plugin is equal to contentBoxRect, mapped to
  // the containing view space, and rounded off.  See
  // LayoutEmbeddedContent::UpdateGeometry. To remove the lossy effect of
  // rounding off, use contentBoxRect directly.
  PhysicalRect unclipped_root_frame_rect = box->PhysicalContentBoxRect();
  box->MapToVisualRectInAncestorSpace(root_view, unclipped_root_frame_rect);
  unclipped_root_frame_rect =
      root_view->GetFrameView()->DocumentToFrame(unclipped_root_frame_rect);

  // The frameRect is already in absolute space of the local frame to the
  // plugin so map it up to the root frame.
  window_rect = FrameRect();
  PhysicalRect layout_window_rect =
      element_->GetDocument().View()->GetLayoutView()->LocalToAbsoluteRect(
          PhysicalRect(window_rect), kTraverseDocumentBoundaries);

  window_rect = PixelSnappedIntRect(layout_window_rect);

  PhysicalRect clipped_root_frame_rect = unclipped_root_frame_rect;
  clipped_root_frame_rect.Intersect(PhysicalRect(
      PhysicalOffset(), PhysicalSize(root_view->GetFrameView()->Size())));

  unclipped_int_local_rect = EnclosingIntRect(box->AbsoluteToLocalRect(
      unclipped_root_frame_rect, kTraverseDocumentBoundaries));
  // As a performance optimization, map the clipped rect separately if is
  // different than the unclipped rect.
  if (clipped_root_frame_rect != unclipped_root_frame_rect) {
    clipped_local_rect = EnclosingIntRect(box->AbsoluteToLocalRect(
        clipped_root_frame_rect, kTraverseDocumentBoundaries));
  } else {
    clipped_local_rect = unclipped_int_local_rect;
  }
}

void WebPluginContainerImpl::CalculateGeometry(IntRect& window_rect,
                                               IntRect& clip_rect,
                                               IntRect& unobscured_rect) {
  // GetDocument().LayoutView() can be null when we receive messages from the
  // plugins while we are destroying a frame.
  // TODO: Can we just check element_->GetDocument().IsActive() ?
  if (element_->GetLayoutObject()->GetDocument().GetLayoutView()) {
    // Take our element and get the clip rect from the enclosing layer and
    // frame view.
    ComputeClipRectsForPlugin(element_, window_rect, clip_rect,
                              unobscured_rect);
  }
}

}  // namespace blink
