// 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_embedder.h"

#include "content/browser/bad_message.h"
#include "content/browser/browser_plugin/browser_plugin_guest.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/drag_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_plugin_guest_manager.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/render_view_host.h"
#include "ui/events/keycodes/keyboard_codes.h"

namespace content {

BrowserPluginEmbedder::BrowserPluginEmbedder(WebContentsImpl* web_contents)
    : WebContentsObserver(web_contents),
      guest_drag_ending_(false),
      weak_ptr_factory_(this) {
}

BrowserPluginEmbedder::~BrowserPluginEmbedder() {
}

// static
BrowserPluginEmbedder* BrowserPluginEmbedder::Create(
    WebContentsImpl* web_contents) {
  return new BrowserPluginEmbedder(web_contents);
}

bool BrowserPluginEmbedder::DragEnteredGuest(BrowserPluginGuest* guest) {
  guest_dragging_over_ = guest->AsWeakPtr();
  return guest_started_drag_.get() == guest;
}

void BrowserPluginEmbedder::DragLeftGuest(BrowserPluginGuest* guest) {
  // Avoid race conditions in switching between guests being hovered over by
  // only un-setting if the caller is marked as the guest being dragged over.
  if (guest_dragging_over_.get() == guest) {
    guest_dragging_over_.reset();
  }
}

// static
bool BrowserPluginEmbedder::CancelDialogs(WebContents* guest_web_contents) {
  static_cast<WebContentsImpl*>(guest_web_contents)
      ->CancelActiveAndPendingDialogs();

  // Returns false to iterate over all guests.
  return false;
}

void BrowserPluginEmbedder::CancelGuestDialogs() {
  if (!GetBrowserPluginGuestManager())
    return;

  GetBrowserPluginGuestManager()->ForEachGuest(
      web_contents(),
      base::BindRepeating(&BrowserPluginEmbedder::CancelDialogs));
}

void BrowserPluginEmbedder::StartDrag(BrowserPluginGuest* guest) {
  guest_started_drag_ = guest->AsWeakPtr();
  guest_drag_ending_ = false;
}

BrowserPluginGuestManager*
BrowserPluginEmbedder::GetBrowserPluginGuestManager() const {
  return web_contents()->GetBrowserContext()->GetGuestManager();
}

void BrowserPluginEmbedder::ClearGuestDragStateIfApplicable() {
  // The order at which we observe SystemDragEnded() and DragSourceEndedAt() is
  // platform dependent.
  // In OSX, we see SystemDragEnded() first, where in aura, we see
  // DragSourceEndedAt() first. For this reason, we check if both methods were
  // called before resetting |guest_started_drag_|.
  if (guest_drag_ending_) {
    if (guest_started_drag_)
      guest_started_drag_.reset();
  } else {
    guest_drag_ending_ = true;
  }
}

// static
bool BrowserPluginEmbedder::DidSendScreenRectsCallback(
   WebContents* guest_web_contents) {
  static_cast<WebContentsImpl*>(guest_web_contents)->SendScreenRects();
  // Not handled => Iterate over all guests.
  return false;
}

void BrowserPluginEmbedder::DidSendScreenRects() {
  if (!GetBrowserPluginGuestManager())
    return;

  GetBrowserPluginGuestManager()->ForEachGuest(
      web_contents(),
      base::BindRepeating(&BrowserPluginEmbedder::DidSendScreenRectsCallback));
}

bool BrowserPluginEmbedder::OnMessageReceived(
    const IPC::Message& message,
    RenderFrameHost* render_frame_host) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(BrowserPluginEmbedder, message,
                                   render_frame_host)
    IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Attach, OnAttach)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void BrowserPluginEmbedder::DragSourceEndedAt(
    float client_x,
    float client_y,
    float screen_x,
    float screen_y,
    blink::WebDragOperation operation) {
  if (guest_started_drag_) {
    gfx::Point guest_offset =
        guest_started_drag_->GetScreenCoordinates(gfx::Point());
    guest_started_drag_->DragSourceEndedAt(client_x - guest_offset.x(),
        client_y - guest_offset.y(), screen_x, screen_y, operation);
  }
  ClearGuestDragStateIfApplicable();
}

void BrowserPluginEmbedder::SystemDragEnded() {
  // When the embedder's drag/drop operation ends, we need to pass the message
  // to the guest that initiated the drag/drop operation. This will ensure that
  // the guest's RVH state is reset properly.
  if (guest_started_drag_)
    guest_started_drag_->EmbedderSystemDragEnded();

  guest_dragging_over_.reset();
  ClearGuestDragStateIfApplicable();
}

bool BrowserPluginEmbedder::OnUpdateDragCursor() {
  return !!guest_dragging_over_;
}

void BrowserPluginEmbedder::OnAttach(
    RenderFrameHost* render_frame_host,
    int browser_plugin_instance_id,
    const BrowserPluginHostMsg_Attach_Params& params) {
  if (!GetBrowserPluginGuestManager()) {
    bad_message::ReceivedBadMessage(
        render_frame_host->GetProcess(),
        bad_message::BPE_UNEXPECTED_MESSAGE_BEFORE_BPGM_CREATION);
    return;
  }
  WebContents* guest_web_contents =
      GetBrowserPluginGuestManager()->GetGuestByInstanceID(
          render_frame_host->GetProcess()->GetID(),
          browser_plugin_instance_id);
  if (!guest_web_contents)
    return;
  BrowserPluginGuest* guest = static_cast<WebContentsImpl*>(guest_web_contents)
                                  ->GetBrowserPluginGuest();
  guest->Attach(browser_plugin_instance_id,
                static_cast<WebContentsImpl*>(web_contents()),
                params);
}

bool BrowserPluginEmbedder::HandleKeyboardEvent(
    const NativeWebKeyboardEvent& event) {
  if ((event.windows_key_code != ui::VKEY_ESCAPE) ||
      (event.GetModifiers() & blink::WebInputEvent::kInputModifiers)) {
    return false;
  }

  bool event_consumed = false;
  GetBrowserPluginGuestManager()->ForEachGuest(
      web_contents(),
      base::BindRepeating(
          &BrowserPluginEmbedder::UnlockMouseIfNecessaryCallback,
          &event_consumed));

  return event_consumed;
}

BrowserPluginGuest* BrowserPluginEmbedder::GetFullPageGuest() {
  WebContentsImpl* guest_contents = static_cast<WebContentsImpl*>(
      GetBrowserPluginGuestManager()->GetFullPageGuest(web_contents()));
  if (!guest_contents)
    return nullptr;
  return guest_contents->GetBrowserPluginGuest();
}

// static
bool BrowserPluginEmbedder::GuestCurrentlyAudibleCallback(WebContents* guest) {
  return guest->IsCurrentlyAudible();
}

bool BrowserPluginEmbedder::AreAnyGuestsCurrentlyAudible() {
  if (!GetBrowserPluginGuestManager())
    return false;

  return GetBrowserPluginGuestManager()->ForEachGuest(
      web_contents(),
      base::BindRepeating(
          &BrowserPluginEmbedder::GuestCurrentlyAudibleCallback));
}

// static
bool BrowserPluginEmbedder::UnlockMouseIfNecessaryCallback(bool* mouse_unlocked,
                                                           WebContents* guest) {
  *mouse_unlocked |= static_cast<WebContentsImpl*>(guest)
                         ->GetBrowserPluginGuest()
                         ->mouse_locked();
  guest->GotResponseToLockMouseRequest(false);

  // Returns false to iterate over all guests.
  return false;
}

}  // namespace content
