// Copyright (c) 2012 The Chromium Embedded Framework Authors.
// Portions 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 "libcef/browser/menu_model_impl.h"

#include <vector>

#include "libcef/browser/thread_util.h"
#include "libcef/common/task_runner_impl.h"

#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "content/public/common/menu_item.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/gfx/geometry/point.h"

namespace {

const int kSeparatorId = -1;
const int kInvalidGroupId = -1;
const int kInvalidCommandId = -1;
const int kDefaultIndex = -1;
const int kInvalidIndex = -2;

// A simple MenuModel implementation that delegates to CefMenuModelImpl.
class CefSimpleMenuModel : public ui::MenuModel {
 public:
  // The Delegate can be NULL, though if it is items can't be checked or
  // disabled.
  explicit CefSimpleMenuModel(CefMenuModelImpl* impl) : impl_(impl) {}

  // MenuModel methods.
  bool HasIcons() const override { return false; }

  int GetItemCount() const override { return impl_->GetCount(); }

  ItemType GetTypeAt(int index) const override {
    switch (impl_->GetTypeAt(index)) {
      case MENUITEMTYPE_COMMAND:
        return TYPE_COMMAND;
      case MENUITEMTYPE_CHECK:
        return TYPE_CHECK;
      case MENUITEMTYPE_RADIO:
        return TYPE_RADIO;
      case MENUITEMTYPE_SEPARATOR:
        return TYPE_SEPARATOR;
      case MENUITEMTYPE_SUBMENU:
        return TYPE_SUBMENU;
      default:
        NOTREACHED();
        return TYPE_COMMAND;
    }
  }

  ui::MenuSeparatorType GetSeparatorTypeAt(int index) const override {
    return ui::NORMAL_SEPARATOR;
  }

  int GetCommandIdAt(int index) const override {
    return impl_->GetCommandIdAt(index);
  }

  base::string16 GetLabelAt(int index) const override {
    return impl_->GetFormattedLabelAt(index);
  }

  bool IsItemDynamicAt(int index) const override { return false; }

  const gfx::FontList* GetLabelFontListAt(int index) const override {
    return impl_->GetLabelFontListAt(index);
  }

  bool GetAcceleratorAt(int index,
                        ui::Accelerator* accelerator) const override {
    int key_code = 0;
    bool shift_pressed = false;
    bool ctrl_pressed = false;
    bool alt_pressed = false;
    if (impl_->GetAcceleratorAt(index, key_code, shift_pressed, ctrl_pressed,
                                alt_pressed)) {
      int modifiers = 0;
      if (shift_pressed)
        modifiers |= ui::EF_SHIFT_DOWN;
      if (ctrl_pressed)
        modifiers |= ui::EF_CONTROL_DOWN;
      if (alt_pressed)
        modifiers |= ui::EF_ALT_DOWN;

      *accelerator =
          ui::Accelerator(static_cast<ui::KeyboardCode>(key_code), modifiers);
      return true;
    }
    return false;
  }

  bool IsItemCheckedAt(int index) const override {
    return impl_->IsCheckedAt(index);
  }

  int GetGroupIdAt(int index) const override {
    return impl_->GetGroupIdAt(index);
  }

  bool GetIconAt(int index, gfx::Image* icon) const override { return false; }

  ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const override {
    return nullptr;
  }

  bool IsEnabledAt(int index) const override {
    return impl_->IsEnabledAt(index);
  }

  bool IsVisibleAt(int index) const override {
    return impl_->IsVisibleAt(index);
  }

  void ActivatedAt(int index) override { ActivatedAt(index, 0); }

  void ActivatedAt(int index, int event_flags) override {
    impl_->ActivatedAt(index, static_cast<cef_event_flags_t>(event_flags));
  }

  MenuModel* GetSubmenuModelAt(int index) const override {
    CefRefPtr<CefMenuModel> submenu = impl_->GetSubMenuAt(index);
    if (submenu.get())
      return static_cast<CefMenuModelImpl*>(submenu.get())->model();
    return nullptr;
  }

  void MouseOutsideMenu(const gfx::Point& screen_point) override {
    impl_->MouseOutsideMenu(screen_point);
  }

  void UnhandledOpenSubmenu(bool is_rtl) override {
    impl_->UnhandledOpenSubmenu(is_rtl);
  }

  void UnhandledCloseSubmenu(bool is_rtl) override {
    impl_->UnhandledCloseSubmenu(is_rtl);
  }

  bool GetTextColor(int index,
                    bool is_minor,
                    bool is_hovered,
                    SkColor* override_color) const override {
    return impl_->GetTextColor(index, is_minor, is_hovered, override_color);
  }

  bool GetBackgroundColor(int index,
                          bool is_hovered,
                          SkColor* override_color) const override {
    return impl_->GetBackgroundColor(index, is_hovered, override_color);
  }

  void MenuWillShow() override { impl_->MenuWillShow(); }

  void MenuWillClose() override { impl_->MenuWillClose(); }

 private:
  CefMenuModelImpl* impl_;

  DISALLOW_COPY_AND_ASSIGN(CefSimpleMenuModel);
};

cef_menu_color_type_t GetMenuColorType(bool is_text,
                                       bool is_accelerator,
                                       bool is_hovered) {
  if (is_text) {
    if (is_accelerator) {
      return is_hovered ? CEF_MENU_COLOR_TEXT_ACCELERATOR_HOVERED
                        : CEF_MENU_COLOR_TEXT_ACCELERATOR;
    }
    return is_hovered ? CEF_MENU_COLOR_TEXT_HOVERED : CEF_MENU_COLOR_TEXT;
  }

  DCHECK(!is_accelerator);
  return is_hovered ? CEF_MENU_COLOR_BACKGROUND_HOVERED
                    : CEF_MENU_COLOR_BACKGROUND;
}

}  // namespace

// static
CefRefPtr<CefMenuModel> CefMenuModel::CreateMenuModel(
    CefRefPtr<CefMenuModelDelegate> delegate) {
  CEF_REQUIRE_UIT_RETURN(nullptr);
  DCHECK(delegate);
  if (!delegate)
    return nullptr;

  CefRefPtr<CefMenuModelImpl> menu_model =
      new CefMenuModelImpl(nullptr, delegate, false);
  return menu_model;
}

struct CefMenuModelImpl::Item {
  Item(cef_menu_item_type_t type,
       int command_id,
       const CefString& label,
       int group_id)
      : type_(type),
        command_id_(command_id),
        label_(label),
        group_id_(group_id) {}

  // Basic information.
  cef_menu_item_type_t type_;
  int command_id_;
  CefString label_;
  int group_id_;
  CefRefPtr<CefMenuModelImpl> submenu_;

  // State information.
  bool enabled_ = true;
  bool visible_ = true;
  bool checked_ = false;

  // Accelerator information.
  bool has_accelerator_ = false;
  int key_code_ = 0;
  bool shift_pressed_ = false;
  bool ctrl_pressed_ = false;
  bool alt_pressed_ = false;

  cef_color_t colors_[CEF_MENU_COLOR_COUNT] = {0};
  gfx::FontList font_list_;
  bool has_font_list_ = false;
};

CefMenuModelImpl::CefMenuModelImpl(
    Delegate* delegate,
    CefRefPtr<CefMenuModelDelegate> menu_model_delegate,
    bool is_submenu)
    : supported_thread_id_(base::PlatformThread::CurrentId()),
      delegate_(delegate),
      menu_model_delegate_(menu_model_delegate),
      is_submenu_(is_submenu) {
  DCHECK(delegate_ || menu_model_delegate_);
  model_.reset(new CefSimpleMenuModel(this));
}

CefMenuModelImpl::~CefMenuModelImpl() {}

bool CefMenuModelImpl::IsSubMenu() {
  if (!VerifyContext())
    return false;
  return is_submenu_;
}

bool CefMenuModelImpl::Clear() {
  if (!VerifyContext())
    return false;

  items_.clear();
  return true;
}

int CefMenuModelImpl::GetCount() {
  if (!VerifyContext())
    return 0;

  return static_cast<int>(items_.size());
}

bool CefMenuModelImpl::AddSeparator() {
  if (!VerifyContext())
    return false;

  AppendItem(
      Item(MENUITEMTYPE_SEPARATOR, kSeparatorId, CefString(), kInvalidGroupId));
  return true;
}

bool CefMenuModelImpl::AddItem(int command_id, const CefString& label) {
  if (!VerifyContext())
    return false;

  AppendItem(Item(MENUITEMTYPE_COMMAND, command_id, label, kInvalidGroupId));
  return true;
}

bool CefMenuModelImpl::AddCheckItem(int command_id, const CefString& label) {
  if (!VerifyContext())
    return false;

  AppendItem(Item(MENUITEMTYPE_CHECK, command_id, label, kInvalidGroupId));
  return true;
}

bool CefMenuModelImpl::AddRadioItem(int command_id,
                                    const CefString& label,
                                    int group_id) {
  if (!VerifyContext())
    return false;

  AppendItem(Item(MENUITEMTYPE_RADIO, command_id, label, group_id));
  return true;
}

CefRefPtr<CefMenuModel> CefMenuModelImpl::AddSubMenu(int command_id,
                                                     const CefString& label) {
  if (!VerifyContext())
    return nullptr;

  Item item(MENUITEMTYPE_SUBMENU, command_id, label, kInvalidGroupId);
  item.submenu_ = new CefMenuModelImpl(delegate_, menu_model_delegate_, true);
  AppendItem(item);
  return item.submenu_.get();
}

bool CefMenuModelImpl::InsertSeparatorAt(int index) {
  if (!VerifyContext())
    return false;

  InsertItemAt(
      Item(MENUITEMTYPE_SEPARATOR, kSeparatorId, CefString(), kInvalidGroupId),
      index);
  return true;
}

bool CefMenuModelImpl::InsertItemAt(int index,
                                    int command_id,
                                    const CefString& label) {
  if (!VerifyContext())
    return false;

  InsertItemAt(Item(MENUITEMTYPE_COMMAND, command_id, label, kInvalidGroupId),
               index);
  return true;
}

bool CefMenuModelImpl::InsertCheckItemAt(int index,
                                         int command_id,
                                         const CefString& label) {
  if (!VerifyContext())
    return false;

  InsertItemAt(Item(MENUITEMTYPE_CHECK, command_id, label, kInvalidGroupId),
               index);
  return true;
}

bool CefMenuModelImpl::InsertRadioItemAt(int index,
                                         int command_id,
                                         const CefString& label,
                                         int group_id) {
  if (!VerifyContext())
    return false;

  InsertItemAt(Item(MENUITEMTYPE_RADIO, command_id, label, group_id), index);
  return true;
}

CefRefPtr<CefMenuModel> CefMenuModelImpl::InsertSubMenuAt(
    int index,
    int command_id,
    const CefString& label) {
  if (!VerifyContext())
    return nullptr;

  Item item(MENUITEMTYPE_SUBMENU, command_id, label, kInvalidGroupId);
  item.submenu_ = new CefMenuModelImpl(delegate_, menu_model_delegate_, true);
  InsertItemAt(item, index);
  return item.submenu_.get();
}

bool CefMenuModelImpl::Remove(int command_id) {
  return RemoveAt(GetIndexOf(command_id));
}

bool CefMenuModelImpl::RemoveAt(int index) {
  if (!VerifyContext())
    return false;

  if (index >= 0 && index < static_cast<int>(items_.size())) {
    items_.erase(items_.begin() + index);
    return true;
  }
  return false;
}

int CefMenuModelImpl::GetIndexOf(int command_id) {
  if (!VerifyContext())
    return kInvalidIndex;

  for (ItemVector::iterator i = items_.begin(); i != items_.end(); ++i) {
    if ((*i).command_id_ == command_id) {
      return static_cast<int>(std::distance(items_.begin(), i));
    }
  }
  return kInvalidIndex;
}

int CefMenuModelImpl::GetCommandIdAt(int index) {
  if (!VerifyContext())
    return kInvalidCommandId;

  if (index >= 0 && index < static_cast<int>(items_.size()))
    return items_[index].command_id_;
  return kInvalidCommandId;
}

bool CefMenuModelImpl::SetCommandIdAt(int index, int command_id) {
  if (!VerifyContext())
    return false;

  if (index >= 0 && index < static_cast<int>(items_.size())) {
    items_[index].command_id_ = command_id;
    return true;
  }
  return false;
}

CefString CefMenuModelImpl::GetLabel(int command_id) {
  return GetLabelAt(GetIndexOf(command_id));
}

CefString CefMenuModelImpl::GetLabelAt(int index) {
  if (!VerifyContext())
    return CefString();

  if (index >= 0 && index < static_cast<int>(items_.size()))
    return items_[index].label_;
  return CefString();
}

bool CefMenuModelImpl::SetLabel(int command_id, const CefString& label) {
  return SetLabelAt(GetIndexOf(command_id), label);
}

bool CefMenuModelImpl::SetLabelAt(int index, const CefString& label) {
  if (!VerifyContext())
    return false;

  if (index >= 0 && index < static_cast<int>(items_.size())) {
    items_[index].label_ = label;
    return true;
  }
  return false;
}

CefMenuModelImpl::MenuItemType CefMenuModelImpl::GetType(int command_id) {
  return GetTypeAt(GetIndexOf(command_id));
}

CefMenuModelImpl::MenuItemType CefMenuModelImpl::GetTypeAt(int index) {
  if (!VerifyContext())
    return MENUITEMTYPE_NONE;

  if (index >= 0 && index < static_cast<int>(items_.size()))
    return items_[index].type_;
  return MENUITEMTYPE_NONE;
}

int CefMenuModelImpl::GetGroupId(int command_id) {
  return GetGroupIdAt(GetIndexOf(command_id));
}

int CefMenuModelImpl::GetGroupIdAt(int index) {
  if (!VerifyContext())
    return kInvalidGroupId;

  if (index >= 0 && index < static_cast<int>(items_.size()))
    return items_[index].group_id_;
  return kInvalidGroupId;
}

bool CefMenuModelImpl::SetGroupId(int command_id, int group_id) {
  return SetGroupIdAt(GetIndexOf(command_id), group_id);
}

bool CefMenuModelImpl::SetGroupIdAt(int index, int group_id) {
  if (!VerifyContext())
    return false;

  if (index >= 0 && index < static_cast<int>(items_.size())) {
    items_[index].group_id_ = group_id;
    return true;
  }
  return false;
}

CefRefPtr<CefMenuModel> CefMenuModelImpl::GetSubMenu(int command_id) {
  return GetSubMenuAt(GetIndexOf(command_id));
}

CefRefPtr<CefMenuModel> CefMenuModelImpl::GetSubMenuAt(int index) {
  if (!VerifyContext())
    return nullptr;

  if (index >= 0 && index < static_cast<int>(items_.size()))
    return items_[index].submenu_.get();
  return nullptr;
}

bool CefMenuModelImpl::IsVisible(int command_id) {
  return IsVisibleAt(GetIndexOf(command_id));
}

bool CefMenuModelImpl::IsVisibleAt(int index) {
  if (!VerifyContext())
    return false;

  if (index >= 0 && index < static_cast<int>(items_.size()))
    return items_[index].visible_;
  return false;
}

bool CefMenuModelImpl::SetVisible(int command_id, bool visible) {
  return SetVisibleAt(GetIndexOf(command_id), visible);
}

bool CefMenuModelImpl::SetVisibleAt(int index, bool visible) {
  if (!VerifyContext())
    return false;

  if (index >= 0 && index < static_cast<int>(items_.size())) {
    items_[index].visible_ = visible;
    return true;
  }
  return false;
}

bool CefMenuModelImpl::IsEnabled(int command_id) {
  return IsEnabledAt(GetIndexOf(command_id));
}

bool CefMenuModelImpl::IsEnabledAt(int index) {
  if (!VerifyContext())
    return false;

  if (index >= 0 && index < static_cast<int>(items_.size()))
    return items_[index].enabled_;
  return false;
}

bool CefMenuModelImpl::SetEnabled(int command_id, bool enabled) {
  return SetEnabledAt(GetIndexOf(command_id), enabled);
}

bool CefMenuModelImpl::SetEnabledAt(int index, bool enabled) {
  if (!VerifyContext())
    return false;

  if (index >= 0 && index < static_cast<int>(items_.size())) {
    items_[index].enabled_ = enabled;
    return true;
  }
  return false;
}

bool CefMenuModelImpl::IsChecked(int command_id) {
  return IsCheckedAt(GetIndexOf(command_id));
}

bool CefMenuModelImpl::IsCheckedAt(int index) {
  if (!VerifyContext())
    return false;

  if (index >= 0 && index < static_cast<int>(items_.size()))
    return items_[index].checked_;
  return false;
}

bool CefMenuModelImpl::SetChecked(int command_id, bool checked) {
  return SetCheckedAt(GetIndexOf(command_id), checked);
}

bool CefMenuModelImpl::SetCheckedAt(int index, bool checked) {
  if (!VerifyContext())
    return false;

  if (index >= 0 && index < static_cast<int>(items_.size())) {
    items_[index].checked_ = checked;
    return true;
  }
  return false;
}

bool CefMenuModelImpl::HasAccelerator(int command_id) {
  return HasAcceleratorAt(GetIndexOf(command_id));
}

bool CefMenuModelImpl::HasAcceleratorAt(int index) {
  if (!VerifyContext())
    return false;

  if (index >= 0 && index < static_cast<int>(items_.size()))
    return items_[index].has_accelerator_;
  return false;
}

bool CefMenuModelImpl::SetAccelerator(int command_id,
                                      int key_code,
                                      bool shift_pressed,
                                      bool ctrl_pressed,
                                      bool alt_pressed) {
  return SetAcceleratorAt(GetIndexOf(command_id), key_code, shift_pressed,
                          ctrl_pressed, alt_pressed);
}

bool CefMenuModelImpl::SetAcceleratorAt(int index,
                                        int key_code,
                                        bool shift_pressed,
                                        bool ctrl_pressed,
                                        bool alt_pressed) {
  if (!VerifyContext())
    return false;

  if (index >= 0 && index < static_cast<int>(items_.size())) {
    Item& item = items_[index];
    item.has_accelerator_ = true;
    item.key_code_ = key_code;
    item.shift_pressed_ = shift_pressed;
    item.ctrl_pressed_ = ctrl_pressed;
    item.alt_pressed_ = alt_pressed;
    return true;
  }
  return false;
}

bool CefMenuModelImpl::RemoveAccelerator(int command_id) {
  return RemoveAcceleratorAt(GetIndexOf(command_id));
}

bool CefMenuModelImpl::RemoveAcceleratorAt(int index) {
  if (!VerifyContext())
    return false;

  if (index >= 0 && index < static_cast<int>(items_.size())) {
    Item& item = items_[index];
    if (item.has_accelerator_) {
      item.has_accelerator_ = false;
      item.key_code_ = 0;
      item.shift_pressed_ = false;
      item.ctrl_pressed_ = false;
      item.alt_pressed_ = false;
    }
    return true;
  }
  return false;
}

bool CefMenuModelImpl::GetAccelerator(int command_id,
                                      int& key_code,
                                      bool& shift_pressed,
                                      bool& ctrl_pressed,
                                      bool& alt_pressed) {
  return GetAcceleratorAt(GetIndexOf(command_id), key_code, shift_pressed,
                          ctrl_pressed, alt_pressed);
}

bool CefMenuModelImpl::GetAcceleratorAt(int index,
                                        int& key_code,
                                        bool& shift_pressed,
                                        bool& ctrl_pressed,
                                        bool& alt_pressed) {
  if (!VerifyContext())
    return false;

  if (index >= 0 && index < static_cast<int>(items_.size())) {
    const Item& item = items_[index];
    if (item.has_accelerator_) {
      key_code = item.key_code_;
      shift_pressed = item.shift_pressed_;
      ctrl_pressed = item.ctrl_pressed_;
      alt_pressed = item.alt_pressed_;
      return true;
    }
  }
  return false;
}

bool CefMenuModelImpl::SetColor(int command_id,
                                cef_menu_color_type_t color_type,
                                cef_color_t color) {
  return SetColorAt(GetIndexOf(command_id), color_type, color);
}

bool CefMenuModelImpl::SetColorAt(int index,
                                  cef_menu_color_type_t color_type,
                                  cef_color_t color) {
  if (!VerifyContext())
    return false;

  if (color_type < 0 || color_type >= CEF_MENU_COLOR_COUNT)
    return false;

  if (index == kDefaultIndex) {
    default_colors_[color_type] = color;
    return true;
  }

  if (index >= 0 && index < static_cast<int>(items_.size())) {
    Item& item = items_[index];
    item.colors_[color_type] = color;
    return true;
  }

  return false;
}

bool CefMenuModelImpl::GetColor(int command_id,
                                cef_menu_color_type_t color_type,
                                cef_color_t& color) {
  return GetColorAt(GetIndexOf(command_id), color_type, color);
}

bool CefMenuModelImpl::GetColorAt(int index,
                                  cef_menu_color_type_t color_type,
                                  cef_color_t& color) {
  if (!VerifyContext())
    return false;

  if (color_type < 0 || color_type >= CEF_MENU_COLOR_COUNT)
    return false;

  if (index == kDefaultIndex) {
    color = default_colors_[color_type];
    return true;
  }

  if (index >= 0 && index < static_cast<int>(items_.size())) {
    Item& item = items_[index];
    color = item.colors_[color_type];
    return true;
  }

  return false;
}

bool CefMenuModelImpl::SetFontList(int command_id, const CefString& font_list) {
  return SetFontListAt(GetIndexOf(command_id), font_list);
}

bool CefMenuModelImpl::SetFontListAt(int index, const CefString& font_list) {
  if (!VerifyContext())
    return false;

  if (index == kDefaultIndex) {
    if (font_list.empty()) {
      has_default_font_list_ = false;
    } else {
      default_font_list_ = gfx::FontList(font_list);
      has_default_font_list_ = true;
    }
    return true;
  }

  if (index >= 0 && index < static_cast<int>(items_.size())) {
    Item& item = items_[index];
    if (font_list.empty()) {
      item.has_font_list_ = false;
    } else {
      item.font_list_ = gfx::FontList(font_list);
      item.has_font_list_ = true;
    }
    return true;
  }
  return false;
}

void CefMenuModelImpl::ActivatedAt(int index, cef_event_flags_t event_flags) {
  if (!VerifyContext())
    return;

  const int command_id = GetCommandIdAt(index);
  if (delegate_)
    delegate_->ExecuteCommand(this, command_id, event_flags);
  if (menu_model_delegate_)
    menu_model_delegate_->ExecuteCommand(this, command_id, event_flags);
}

void CefMenuModelImpl::MouseOutsideMenu(const gfx::Point& screen_point) {
  if (!VerifyContext())
    return;

  // Allow the callstack to unwind before notifying the delegate since it may
  // result in the menu being destroyed.
  CefTaskRunnerImpl::GetCurrentTaskRunner()->PostTask(
      FROM_HERE,
      base::Bind(&CefMenuModelImpl::OnMouseOutsideMenu, this, screen_point));
}

void CefMenuModelImpl::UnhandledOpenSubmenu(bool is_rtl) {
  if (!VerifyContext())
    return;

  // Allow the callstack to unwind before notifying the delegate since it may
  // result in the menu being destroyed.
  CefTaskRunnerImpl::GetCurrentTaskRunner()->PostTask(
      FROM_HERE,
      base::Bind(&CefMenuModelImpl::OnUnhandledOpenSubmenu, this, is_rtl));
}

void CefMenuModelImpl::UnhandledCloseSubmenu(bool is_rtl) {
  if (!VerifyContext())
    return;

  // Allow the callstack to unwind before notifying the delegate since it may
  // result in the menu being destroyed.
  CefTaskRunnerImpl::GetCurrentTaskRunner()->PostTask(
      FROM_HERE,
      base::Bind(&CefMenuModelImpl::OnUnhandledCloseSubmenu, this, is_rtl));
}

bool CefMenuModelImpl::GetTextColor(int index,
                                    bool is_accelerator,
                                    bool is_hovered,
                                    SkColor* override_color) const {
  if (index >= 0 && index < static_cast<int>(items_.size())) {
    const Item& item = items_[index];
    if (!item.enabled_) {
      // Use accelerator color for disabled item text.
      is_accelerator = true;
    }

    const cef_menu_color_type_t color_type =
        GetMenuColorType(true, is_accelerator, is_hovered);
    if (item.colors_[color_type] != 0) {
      *override_color = item.colors_[color_type];
      return true;
    }
  }

  const cef_menu_color_type_t color_type =
      GetMenuColorType(true, is_accelerator, is_hovered);
  if (default_colors_[color_type] != 0) {
    *override_color = default_colors_[color_type];
    return true;
  }

  return false;
}

bool CefMenuModelImpl::GetBackgroundColor(int index,
                                          bool is_hovered,
                                          SkColor* override_color) const {
  const cef_menu_color_type_t color_type =
      GetMenuColorType(false, false, is_hovered);

  if (index >= 0 && index < static_cast<int>(items_.size())) {
    const Item& item = items_[index];
    if (item.colors_[color_type] != 0) {
      *override_color = item.colors_[color_type];
      return true;
    }
  }

  if (default_colors_[color_type] != 0) {
    *override_color = default_colors_[color_type];
    return true;
  }

  return false;
}

void CefMenuModelImpl::MenuWillShow() {
  if (!VerifyContext())
    return;

  if (delegate_)
    delegate_->MenuWillShow(this);
  if (menu_model_delegate_)
    menu_model_delegate_->MenuWillShow(this);
}

void CefMenuModelImpl::MenuWillClose() {
  if (!VerifyContext())
    return;

  if (!auto_notify_menu_closed_)
    return;

  // Due to how menus work on the different platforms, ActivatedAt will be
  // called after this.  It's more convenient for the delegate to be called
  // afterwards, though, so post a task.
  CefTaskRunnerImpl::GetCurrentTaskRunner()->PostTask(
      FROM_HERE, base::Bind(&CefMenuModelImpl::OnMenuClosed, this));
}

base::string16 CefMenuModelImpl::GetFormattedLabelAt(int index) {
  base::string16 label = GetLabelAt(index).ToString16();
  if (delegate_)
    delegate_->FormatLabel(this, label);
  if (menu_model_delegate_) {
    CefString new_label = label;
    if (menu_model_delegate_->FormatLabel(this, new_label))
      label = new_label;
  }
  return label;
}

const gfx::FontList* CefMenuModelImpl::GetLabelFontListAt(int index) const {
  if (index >= 0 && index < static_cast<int>(items_.size())) {
    const Item& item = items_[index];
    if (item.has_font_list_)
      return &item.font_list_;
  }

  if (has_default_font_list_)
    return &default_font_list_;
  return nullptr;
}

bool CefMenuModelImpl::VerifyRefCount() {
  if (!VerifyContext())
    return false;

  if (!HasOneRef())
    return false;

  for (ItemVector::iterator i = items_.begin(); i != items_.end(); ++i) {
    if ((*i).submenu_.get()) {
      if (!(*i).submenu_->VerifyRefCount())
        return false;
    }
  }

  return true;
}

void CefMenuModelImpl::AddMenuItem(const content::MenuItem& menu_item) {
  const int command_id = static_cast<int>(menu_item.action);

  switch (menu_item.type) {
    case content::MenuItem::OPTION:
      AddItem(command_id, menu_item.label);
      break;
    case content::MenuItem::CHECKABLE_OPTION:
      AddCheckItem(command_id, menu_item.label);
      break;
    case content::MenuItem::GROUP:
      AddRadioItem(command_id, menu_item.label, 0);
      break;
    case content::MenuItem::SEPARATOR:
      AddSeparator();
      break;
    case content::MenuItem::SUBMENU: {
      CefRefPtr<CefMenuModelImpl> sub_menu = static_cast<CefMenuModelImpl*>(
          AddSubMenu(command_id, menu_item.label).get());
      for (size_t i = 0; i < menu_item.submenu.size(); ++i)
        sub_menu->AddMenuItem(menu_item.submenu[i]);
      break;
    }
  }

  if (!menu_item.enabled && menu_item.type != content::MenuItem::SEPARATOR)
    SetEnabled(command_id, false);

  if (menu_item.checked &&
      (menu_item.type == content::MenuItem::CHECKABLE_OPTION ||
       menu_item.type == content::MenuItem::GROUP)) {
    SetChecked(command_id, true);
  }
}

void CefMenuModelImpl::NotifyMenuClosed() {
  DCHECK(!auto_notify_menu_closed_);
  OnMenuClosed();
}

void CefMenuModelImpl::AppendItem(const Item& item) {
  ValidateItem(item);
  items_.push_back(item);
}

void CefMenuModelImpl::InsertItemAt(const Item& item, int index) {
  // Sanitize the index.
  if (index < 0)
    index = 0;
  else if (index > static_cast<int>(items_.size()))
    index = items_.size();

  ValidateItem(item);
  items_.insert(items_.begin() + index, item);
}

void CefMenuModelImpl::ValidateItem(const Item& item) {
#if DCHECK_IS_ON()
  if (item.type_ == MENUITEMTYPE_SEPARATOR) {
    DCHECK_EQ(item.command_id_, kSeparatorId);
  } else {
    DCHECK_GE(item.command_id_, 0);
  }
#endif
}

void CefMenuModelImpl::OnMouseOutsideMenu(const gfx::Point& screen_point) {
  if (delegate_)
    delegate_->MouseOutsideMenu(this, screen_point);
  if (menu_model_delegate_) {
    menu_model_delegate_->MouseOutsideMenu(
        this, CefPoint(screen_point.x(), screen_point.y()));
  }
}

void CefMenuModelImpl::OnUnhandledOpenSubmenu(bool is_rtl) {
  if (delegate_)
    delegate_->UnhandledOpenSubmenu(this, is_rtl);
  if (menu_model_delegate_)
    menu_model_delegate_->UnhandledOpenSubmenu(this, is_rtl);
}

void CefMenuModelImpl::OnUnhandledCloseSubmenu(bool is_rtl) {
  if (delegate_)
    delegate_->UnhandledCloseSubmenu(this, is_rtl);
  if (menu_model_delegate_)
    menu_model_delegate_->UnhandledCloseSubmenu(this, is_rtl);
}

void CefMenuModelImpl::OnMenuClosed() {
  if (delegate_)
    delegate_->MenuClosed(this);
  if (menu_model_delegate_)
    menu_model_delegate_->MenuClosed(this);
}

bool CefMenuModelImpl::VerifyContext() {
  if (base::PlatformThread::CurrentId() != supported_thread_id_) {
    // This object should only be accessed from the thread that created it.
    NOTREACHED();
    return false;
  }

  return true;
}
