// 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/browser/extensions/context_menu_matcher.h"

#include <string>

#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/chromeos_buildflags.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/common/extensions/api/context_menus.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/context_menu_params.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_util.h"
#include "ui/base/models/image_model.h"
#include "ui/gfx/favicon_size.h"
#include "ui/gfx/image/image.h"

namespace extensions {

namespace {

// The range of command IDs reserved for extension's custom menus.
// TODO(oshima): These values will be injected by embedders.
int extensions_context_custom_first = IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST;
int extensions_context_custom_last = IDC_EXTENSIONS_CONTEXT_CUSTOM_LAST;

}  // namespace

// static
const size_t ContextMenuMatcher::kMaxExtensionItemTitleLength = 75;

// static
int ContextMenuMatcher::ConvertToExtensionsCustomCommandId(int id) {
  return extensions_context_custom_first + id;
}

// static
bool ContextMenuMatcher::IsExtensionsCustomCommandId(int id) {
  return id >= extensions_context_custom_first &&
         id <= extensions_context_custom_last;
}

ContextMenuMatcher::ContextMenuMatcher(
    content::BrowserContext* browser_context,
    ui::SimpleMenuModel::Delegate* delegate,
    ui::SimpleMenuModel* menu_model,
    base::RepeatingCallback<bool(const MenuItem*)> filter)
    : browser_context_(browser_context),
      menu_model_(menu_model),
      delegate_(delegate),
      filter_(filter),
      is_smart_text_selection_enabled_(false) {}

void ContextMenuMatcher::AppendExtensionItems(
    const MenuItem::ExtensionKey& extension_key,
    const base::string16& selection_text,
    int* index,
    bool is_action_menu) {
  DCHECK_GE(*index, 0);
  int max_index =
      extensions_context_custom_last - extensions_context_custom_first;
  if (*index >= max_index)
    return;

  const Extension* extension = NULL;
  MenuItem::List items;
  bool can_cross_incognito;
  if (!GetRelevantExtensionTopLevelItems(
          extension_key, &extension, &can_cross_incognito, &items))
    return;

  if (items.empty())
    return;

  bool prepend_separator = false;

#if !BUILDFLAG(IS_CHROMEOS_ASH)
  // If this is the first extension-provided menu item, and there are other
  // items in the menu, and the last item is not a separator add a separator.
  // Also, don't add separators when Smart Text Selection is enabled. Smart
  // actions are grouped with extensions and the separator logic is
  // handled by them.
  prepend_separator = *index == 0 && menu_model_->GetItemCount() &&
                      !is_smart_text_selection_enabled_;
#endif

  // Extensions (other than platform apps) are only allowed one top-level slot
  // (and it can't be a radio or checkbox item because we are going to put the
  // extension icon next to it), unless the context menu is an an action menu.
  // Action menus do not include the extension action, and they only include
  // items from one extension, so they are not placed within a submenu.
  // Otherwise, we automatically push them into a submenu if there is more than
  // one top-level item.
  if (extension->is_platform_app() || is_action_menu) {
    if (prepend_separator)
      menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
    RecursivelyAppendExtensionItems(items,
                                    can_cross_incognito,
                                    selection_text,
                                    menu_model_,
                                    index,
                                    is_action_menu);
  } else {
    int menu_id = ConvertToExtensionsCustomCommandId(*index);
    (*index)++;
    base::string16 title;
    MenuItem::List submenu_items;

    if (items.size() > 1 || items[0]->type() != MenuItem::NORMAL) {
      if (prepend_separator)
        menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
      title = base::UTF8ToUTF16(extension->name());
      submenu_items = items;
    } else {
      // The top-level menu item, |item[0]|, is sandwiched between two menu
      // separators. If the top-level menu item is visible, its preceding
      // separator should be included in the UI model, so that both separators
      // are shown. Otherwise if the top-level menu item is hidden, the
      // preceding separator should be excluded, so that only one of the two
      // separators remain.
      if (prepend_separator && items[0]->visible())
        menu_model_->AddSeparator(ui::NORMAL_SEPARATOR);
      MenuItem* item = items[0];
      extension_item_map_[menu_id] = item->id();
      title = item->TitleWithReplacement(selection_text,
                                         kMaxExtensionItemTitleLength);
      submenu_items = GetRelevantExtensionItems(item->children(),
                                                can_cross_incognito);
    }

    // Now add our item(s) to the menu_model_.
    if (submenu_items.empty()) {
      menu_model_->AddItem(menu_id, title);
    } else {
      ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(delegate_);
      extension_menu_models_.push_back(base::WrapUnique(submenu));
      menu_model_->AddSubMenu(menu_id, title, submenu);
      RecursivelyAppendExtensionItems(submenu_items, can_cross_incognito,
                                      selection_text, submenu, index,
                                      false);  // is_action_menu_top_level
    }
    if (!is_action_menu)
      SetExtensionIcon(extension_key.extension_id);
  }
}

bool ContextMenuMatcher::HasVisibleItems(ui::MenuModel* menu_model) const {
  for (int index = 0; index < menu_model->GetItemCount(); index++) {
    if (!menu_model->IsVisibleAt(index))
      continue;

    ui::MenuModel* submenu_model = menu_model->GetSubmenuModelAt(index);
    if (submenu_model) {
      // If the item is a menu, we recursively check if it has any visible
      // children.
      return HasVisibleItems(submenu_model);
    }
    // Otherwise, this is itself a visible child.
    return true;
  }
  return false;
}

void ContextMenuMatcher::Clear() {
  extension_item_map_.clear();
  extension_menu_models_.clear();
}

base::string16 ContextMenuMatcher::GetTopLevelContextMenuTitle(
    const MenuItem::ExtensionKey& extension_key,
    const base::string16& selection_text) {
  const Extension* extension = NULL;
  MenuItem::List items;
  bool can_cross_incognito;
  GetRelevantExtensionTopLevelItems(
      extension_key, &extension, &can_cross_incognito, &items);

  base::string16 title;

  if (items.empty() ||
      items.size() > 1 ||
      items[0]->type() != MenuItem::NORMAL) {
    title = base::UTF8ToUTF16(extension->name());
  } else {
    MenuItem* item = items[0];
    title = item->TitleWithReplacement(
        selection_text, kMaxExtensionItemTitleLength);
  }
  return title;
}

bool ContextMenuMatcher::IsCommandIdChecked(int command_id) const {
  MenuItem* item = GetExtensionMenuItem(command_id);
  if (!item)
    return false;
  return item->checked();
}

bool ContextMenuMatcher::IsCommandIdVisible(int command_id) const {
  MenuItem* item = GetExtensionMenuItem(command_id);
  // The context menu code creates a top-level menu item, labeled with the
  // extension's name, that is a container of an extension's menu items. This
  // top-level menu item is not added to the context menu, so checking its
  // visibility is a special case handled below. This top-level menu item should
  // be displayed only if it has an invisible submenu item.
  if (!item && ContextMenuMatcher::IsExtensionsCustomCommandId(command_id)) {
    ui::MenuModel* model = menu_model_;
    int index = 0;
    if (ui::MenuModel::GetModelAndIndexForCommandId(command_id, &model,
                                                    &index)) {
      ui::MenuModel* submenu_model = model->GetSubmenuModelAt(index);
      // TODO(ghazale): Find out why submenu_model might be null. In other
      // words, in which circumstance it can be an extensions custom command ID
      // which does not have an associated item, but it's submenu_model is null.
      if (submenu_model)
        return HasVisibleItems(submenu_model);
    }
    return false;
  } else if (item) {
    return item->visible();
  } else {
    return false;
  }
}

bool ContextMenuMatcher::IsCommandIdEnabled(int command_id) const {
  MenuItem* item = GetExtensionMenuItem(command_id);
  if (!item)
    return true;
  return item->enabled();
}

void ContextMenuMatcher::ExecuteCommand(
    int command_id,
    content::WebContents* web_contents,
    content::RenderFrameHost* render_frame_host,
    const content::ContextMenuParams& params) {
  MenuItem* item = GetExtensionMenuItem(command_id);
  if (!item)
    return;

  MenuManager* manager = MenuManager::Get(browser_context_);
  manager->ExecuteCommand(browser_context_, web_contents, render_frame_host,
                          params, item->id());
}

bool ContextMenuMatcher::GetRelevantExtensionTopLevelItems(
    const MenuItem::ExtensionKey& extension_key,
    const Extension** extension,
    bool* can_cross_incognito,
    MenuItem::List* items) {
  *extension = ExtensionRegistry::Get(
      browser_context_)->enabled_extensions().GetByID(
          extension_key.extension_id);
  if (!*extension)
    return false;

  // Find matching items.
  MenuManager* manager = MenuManager::Get(browser_context_);
  const MenuItem::OwnedList* all_items = manager->MenuItems(extension_key);
  if (!all_items || all_items->empty())
    return false;

  *can_cross_incognito = util::CanCrossIncognito(*extension, browser_context_);
  *items = GetRelevantExtensionItems(*all_items, *can_cross_incognito);

  return true;
}

MenuItem::List ContextMenuMatcher::GetRelevantExtensionItems(
    const MenuItem::OwnedList& items,
    bool can_cross_incognito) {
  MenuItem::List result;
  for (auto i = items.begin(); i != items.end(); ++i) {
    MenuItem* item = i->get();

    if (!filter_.Run(item))
      continue;

    if (item->id().incognito == browser_context_->IsOffTheRecord() ||
        can_cross_incognito)
      result.push_back(item);
  }
  return result;
}

void ContextMenuMatcher::RecursivelyAppendExtensionItems(
    const MenuItem::List& items,
    bool can_cross_incognito,
    const base::string16& selection_text,
    ui::SimpleMenuModel* menu_model,
    int* index,
    bool is_action_menu_top_level) {
  MenuItem::Type last_type = MenuItem::NORMAL;
  int radio_group_id = 1;
  int num_visible_items = 0;

  bool enable_separators = false;

#if !BUILDFLAG(IS_CHROMEOS_ASH)
  enable_separators = true;
#endif

  for (auto i = items.begin(); i != items.end(); ++i) {
    MenuItem* item = *i;

    // If last item was of type radio but the current one isn't, auto-insert
    // a separator.  The converse case is handled below.
    if (last_type == MenuItem::RADIO && item->type() != MenuItem::RADIO &&
        enable_separators) {
      menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
      last_type = MenuItem::SEPARATOR;
    }

    int menu_id = ConvertToExtensionsCustomCommandId(*index);
    // Action context menus have a limit for top level extension items to
    // prevent control items from being pushed off the screen, since extension
    // items will not be placed in a submenu.
    const int top_level_limit = api::context_menus::ACTION_MENU_TOP_LEVEL_LIMIT;
    if (menu_id >= extensions_context_custom_last ||
        (is_action_menu_top_level && num_visible_items >= top_level_limit))
      return;

    ++(*index);
    if (item->visible())
      ++num_visible_items;

    extension_item_map_[menu_id] = item->id();
    base::string16 title = item->TitleWithReplacement(selection_text,
                                                kMaxExtensionItemTitleLength);
    if (item->type() == MenuItem::NORMAL) {
      MenuItem::List children =
          GetRelevantExtensionItems(item->children(), can_cross_incognito);
      if (children.empty()) {
        menu_model->AddItem(menu_id, title);
      } else {
        ui::SimpleMenuModel* submenu = new ui::SimpleMenuModel(delegate_);
        extension_menu_models_.push_back(base::WrapUnique(submenu));
        menu_model->AddSubMenu(menu_id, title, submenu);
        RecursivelyAppendExtensionItems(children, can_cross_incognito,
                                        selection_text, submenu, index,
                                        false);  // is_action_menu_top_level
      }
    } else if (item->type() == MenuItem::CHECKBOX) {
      menu_model->AddCheckItem(menu_id, title);
    } else if (item->type() == MenuItem::RADIO) {
      if (i != items.begin() &&
          last_type != MenuItem::RADIO) {
        radio_group_id++;

        // Auto-append a separator if needed.
        if (enable_separators)
          menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
      }

      menu_model->AddRadioItem(menu_id, title, radio_group_id);
    } else if (item->type() == MenuItem::SEPARATOR && enable_separators) {
      menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
    }
    last_type = item->type();
  }
}

MenuItem* ContextMenuMatcher::GetExtensionMenuItem(int id) const {
  MenuManager* manager = MenuManager::Get(browser_context_);
  auto i = extension_item_map_.find(id);
  if (i != extension_item_map_.end()) {
    MenuItem* item = manager->GetItemById(i->second);
    if (item)
      return item;
  }
  return NULL;
}

void ContextMenuMatcher::SetExtensionIcon(const std::string& extension_id) {
  MenuManager* menu_manager = MenuManager::Get(browser_context_);

  int index = menu_model_->GetItemCount() - 1;
  DCHECK_GE(index, 0);

  gfx::Image icon = menu_manager->GetIconForExtension(extension_id);
  DCHECK_EQ(gfx::kFaviconSize, icon.Width());
  DCHECK_EQ(gfx::kFaviconSize, icon.Height());
  menu_model_->SetIcon(index, ui::ImageModel::FromImage(icon));
}

}  // namespace extensions
