// 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 "chrome/renderer/pepper/pepper_flash_menu_host.h"

#include "base/strings/utf_string_conversions.h"
#include "content/public/common/context_menu_params.h"
#include "content/public/renderer/render_view.h"
#include "content/public/renderer/renderer_ppapi_host.h"
#include "ipc/ipc_message.h"
#include "ppapi/c/private/ppb_flash_menu.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/serialized_flash_menu.h"
#include "ui/gfx/point.h"

namespace chrome {

namespace {

// Maximum depth of submenus allowed (e.g., 1 indicates that submenus are
// allowed, but not sub-submenus).
const size_t kMaxMenuDepth = 2;

// Maximum number of entries in any single menu (including separators).
const size_t kMaxMenuEntries = 50;

// Maximum total number of entries in the |menu_id_map| (see below).
// (Limit to 500 real entries; reserve the 0 action as an invalid entry.)
const size_t kMaxMenuIdMapEntries = 501;

// Converts menu data from one form to another.
//  - |depth| is the current nested depth (call it starting with 0).
//  - |menu_id_map| is such that |menu_id_map[output_item.action] ==
//    input_item.id| (where |action| is what a |MenuItem| has, |id| is what a
//    |PP_Flash_MenuItem| has).
bool ConvertMenuData(const PP_Flash_Menu* in_menu,
                     size_t depth,
                     std::vector<content::MenuItem>* out_menu,
                     std::vector<int32_t>* menu_id_map) {
  if (depth > kMaxMenuDepth || !in_menu)
    return false;

  // Clear the output, just in case.
  out_menu->clear();

  if (!in_menu->count)
    return true;  // Nothing else to do.

  if (!in_menu->items || in_menu->count > kMaxMenuEntries)
    return false;
  for (uint32_t i = 0; i < in_menu->count; i++) {
    content::MenuItem item;

    PP_Flash_MenuItem_Type type = in_menu->items[i].type;
    switch (type) {
      case PP_FLASH_MENUITEM_TYPE_NORMAL:
        item.type = content::MenuItem::OPTION;
        break;
      case PP_FLASH_MENUITEM_TYPE_CHECKBOX:
        item.type = content::MenuItem::CHECKABLE_OPTION;
        break;
      case PP_FLASH_MENUITEM_TYPE_SEPARATOR:
        item.type = content::MenuItem::SEPARATOR;
        break;
      case PP_FLASH_MENUITEM_TYPE_SUBMENU:
        item.type = content::MenuItem::SUBMENU;
        break;
      default:
        return false;
    }
    if (in_menu->items[i].name)
      item.label = UTF8ToUTF16(in_menu->items[i].name);
    if (menu_id_map->size() >= kMaxMenuIdMapEntries)
      return false;
    item.action = static_cast<unsigned>(menu_id_map->size());
    // This sets |(*menu_id_map)[item.action] = in_menu->items[i].id|.
    menu_id_map->push_back(in_menu->items[i].id);
    item.enabled = PP_ToBool(in_menu->items[i].enabled);
    item.checked = PP_ToBool(in_menu->items[i].checked);
    if (type == PP_FLASH_MENUITEM_TYPE_SUBMENU) {
      if (!ConvertMenuData(in_menu->items[i].submenu, depth + 1, &item.submenu,
                           menu_id_map))
        return false;
    }

    out_menu->push_back(item);
  }

  return true;
}

}  // namespace

PepperFlashMenuHost::PepperFlashMenuHost(
    content::RendererPpapiHost* host,
    PP_Instance instance,
    PP_Resource resource,
    const ppapi::proxy::SerializedFlashMenu& serial_menu)
    : ppapi::host::ResourceHost(host->GetPpapiHost(), instance, resource),
      renderer_ppapi_host_(host),
      showing_context_menu_(false),
      context_menu_request_id_(0),
      has_saved_context_menu_action_(false),
      saved_context_menu_action_(0) {
  menu_id_map_.push_back(0);  // Reserve |menu_id_map_[0]|.
  if (!ConvertMenuData(serial_menu.pp_menu(), 0, &menu_data_, &menu_id_map_)) {
    menu_data_.clear();
    menu_id_map_.clear();
  }
}

PepperFlashMenuHost::~PepperFlashMenuHost() {
  if (showing_context_menu_) {
    content::RenderView* render_view =
        renderer_ppapi_host_->GetRenderViewForInstance(pp_instance());
    if (render_view)
      render_view->CancelContextMenu(context_menu_request_id_);
  }
}

int32_t PepperFlashMenuHost::OnResourceMessageReceived(
    const IPC::Message& msg,
    ppapi::host::HostMessageContext* context) {
  IPC_BEGIN_MESSAGE_MAP(PepperFlashMenuHost, msg)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FlashMenu_Show,
                                      OnHostMsgShow)
  IPC_END_MESSAGE_MAP()
  return PP_ERROR_FAILED;
}

int32_t PepperFlashMenuHost::OnHostMsgShow(
    ppapi::host::HostMessageContext* context,
    const PP_Point& location) {
  // Note that all early returns must do a SendMenuReply. The sync result for
  // this message isn't used, so to forward the error to the plugin, we need to
  // additionally call SendMenuReply explicitly.
  if (menu_data_.empty()) {
    SendMenuReply(PP_ERROR_FAILED, -1);
    return PP_ERROR_FAILED;
  }
  if (showing_context_menu_) {
    SendMenuReply(PP_ERROR_INPROGRESS, -1);
    return PP_ERROR_INPROGRESS;
  }

  content::RenderView* render_view =
      renderer_ppapi_host_->GetRenderViewForInstance(pp_instance());

  content::ContextMenuParams params;
  params.x = location.x;
  params.y = location.y;
  params.custom_context.is_pepper_menu = true;
  params.custom_context.render_widget_id =
      renderer_ppapi_host_->GetRoutingIDForWidget(pp_instance());
  params.custom_items = menu_data_;

  // Transform the position to be in render view's coordinates.
  gfx::Point render_view_pt = renderer_ppapi_host_->PluginPointToRenderView(
      pp_instance(), gfx::Point(location.x, location.y));
  params.x = render_view_pt.x();
  params.y = render_view_pt.y();

  showing_context_menu_ = true;
  context_menu_request_id_ = render_view->ShowContextMenu(this, params);

  // Note: the show message is sync so this OK is for the sync reply which we
  // don't actually use (see the comment in the resource file for this). The
  // async message containing the context menu action will be sent in the
  // future.
  return PP_OK;
}

void PepperFlashMenuHost::OnMenuAction(int request_id, unsigned action) {
  // Just save the action.
  DCHECK(!has_saved_context_menu_action_);
  has_saved_context_menu_action_ = true;
  saved_context_menu_action_ = action;
}

void PepperFlashMenuHost::OnMenuClosed(int request_id) {
  if (has_saved_context_menu_action_ &&
      saved_context_menu_action_ < menu_id_map_.size()) {
    SendMenuReply(PP_OK, menu_id_map_[saved_context_menu_action_]);
    has_saved_context_menu_action_ = false;
    saved_context_menu_action_ = 0;
  } else {
    SendMenuReply(PP_ERROR_USERCANCEL, -1);
  }

  showing_context_menu_ = false;
  context_menu_request_id_ = 0;
}

void PepperFlashMenuHost::SendMenuReply(int32_t result, int action) {
  ppapi::host::ReplyMessageContext reply_context(
      ppapi::proxy::ResourceMessageReplyParams(pp_resource(), 0),
      NULL, MSG_ROUTING_NONE);
  reply_context.params.set_result(result);
  host()->SendReply(reply_context,
                    PpapiPluginMsg_FlashMenu_ShowReply(action));

}

}  // namespace chrome
