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

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

}
