blob: 22e75cd76aebde882565747e178db41d3efacfb1 [file] [log] [blame]
// Copyright 2014 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 "athena/content/render_view_context_menu_impl.h"
#include "athena/strings/grit/athena_strings.h"
#include "components/renderer_context_menu/context_menu_content_type.h"
#include "components/renderer_context_menu/views/toolkit_delegate_views.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "third_party/WebKit/public/web/WebContextMenuData.h"
#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/window.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/widget/widget.h"
namespace athena {
using blink::WebContextMenuData;
namespace {
enum {
// Nativation
CMD_BACK = 0,
CMD_FORWARD,
CMD_RELOAD,
CMD_VIEW_SOURCE,
// Link
CMD_OPEN_LINK_NEW_ACTIVITY,
// Edit
CMD_UNDO,
CMD_REDO,
CMD_CUT,
CMD_COPY,
CMD_PASTE,
CMD_PASTE_AND_MATCH_STYLE,
CMD_DELETE,
CMD_SELECT_ALL,
CMD_LAST,
};
// Max number of custom command ids allowd.
const int kNumCustomCommandIds = 1000;
// TODO(oshima): Move IDS for context menus to components/renderer_context_menu
// and replace hardcoded strings below.
void AppendPageItems(ui::SimpleMenuModel* menu_model) {
menu_model->AddItem(CMD_BACK,
l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_BACK));
menu_model->AddItem(CMD_FORWARD,
l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_FORWARD));
menu_model->AddItem(CMD_RELOAD,
l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_RELOAD));
menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
menu_model->AddItem(
CMD_VIEW_SOURCE,
l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_VIEWPAGESOURCE));
}
void AppendLinkItems(const content::ContextMenuParams& params,
ui::SimpleMenuModel* menu_model) {
if (!params.link_url.is_empty())
menu_model->AddItem(
CMD_OPEN_LINK_NEW_ACTIVITY,
l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_OPENLINKNEWACTIVITY));
}
void AppendEditableItems(ui::SimpleMenuModel* menu_model) {
menu_model->AddItem(CMD_UNDO,
l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_UNDO));
menu_model->AddItem(CMD_REDO,
l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_REDO));
menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
menu_model->AddItem(CMD_CUT,
l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_CUT));
menu_model->AddItem(CMD_COPY,
l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_COPY));
menu_model->AddItem(CMD_PASTE,
l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_PASTE));
menu_model->AddItem(
CMD_PASTE_AND_MATCH_STYLE,
l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_PASTE_AND_MATCH_STYLE));
menu_model->AddItem(CMD_DELETE,
l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_DELETE));
menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
menu_model->AddItem(CMD_SELECT_ALL,
l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_SELECTALL));
}
} // namespace
RenderViewContextMenuImpl::RenderViewContextMenuImpl(
content::RenderFrameHost* render_frame_host,
const content::ContextMenuParams& params)
: RenderViewContextMenuBase(render_frame_host, params) {
SetContentCustomCommandIdRange(CMD_LAST, CMD_LAST + kNumCustomCommandIds);
// TODO(oshima): Support other types
set_content_type(
new ContextMenuContentType(source_web_contents_, params, true));
set_toolkit_delegate(scoped_ptr<ToolkitDelegate>(new ToolkitDelegateViews));
}
RenderViewContextMenuImpl::~RenderViewContextMenuImpl() {
}
void RenderViewContextMenuImpl::RunMenuAt(views::Widget* parent,
const gfx::Point& point,
ui::MenuSourceType type) {
static_cast<ToolkitDelegateViews*>(toolkit_delegate())
->RunMenuAt(parent, point, type);
}
void RenderViewContextMenuImpl::Show() {
// Menus need a Widget to work. If we're not the active tab we won't
// necessarily be in a widget.
views::Widget* top_level_widget = GetTopLevelWidget();
if (!top_level_widget)
return;
// Don't show empty menus.
if (menu_model().GetItemCount() == 0)
return;
gfx::Point screen_point(params().x, params().y);
// Convert from target window coordinates to root window coordinates.
aura::Window* target_window = GetActiveNativeView();
aura::Window* root_window = target_window->GetRootWindow();
aura::client::ScreenPositionClient* screen_position_client =
aura::client::GetScreenPositionClient(root_window);
if (screen_position_client)
screen_position_client->ConvertPointToScreen(target_window, &screen_point);
// Enable recursive tasks on the message loop so we can get updates while
// the context menu is being displayed.
base::MessageLoop::ScopedNestableTaskAllower allow(
base::MessageLoop::current());
RunMenuAt(top_level_widget, screen_point, params().source_type);
}
void RenderViewContextMenuImpl::InitMenu() {
RenderViewContextMenuBase::InitMenu();
bool needs_separator = false;
if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_PAGE)) {
AppendPageItems(&menu_model_);
needs_separator = true;
}
if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_LINK)) {
if (needs_separator)
AddSeparator();
AppendLinkItems(params_, &menu_model_);
needs_separator = true;
}
if (content_type_->SupportsGroup(
ContextMenuContentType::ITEM_GROUP_EDITABLE)) {
if (needs_separator)
AddSeparator();
AppendEditableItems(&menu_model_);
}
}
void RenderViewContextMenuImpl::RecordShownItem(int id) {
// TODO(oshima): Imelement UMA stats. crbug.com/401673
NOTIMPLEMENTED();
}
void RenderViewContextMenuImpl::RecordUsedItem(int id) {
// TODO(oshima): Imelement UMA stats. crbug.com/401673
NOTIMPLEMENTED();
}
#if defined(ENABLE_PLUGINS)
void RenderViewContextMenuImpl::HandleAuthorizeAllPlugins() {
}
#endif
void RenderViewContextMenuImpl::NotifyMenuShown() {
}
void RenderViewContextMenuImpl::NotifyURLOpened(
const GURL& url,
content::WebContents* new_contents) {
}
bool RenderViewContextMenuImpl::GetAcceleratorForCommandId(
int command_id,
ui::Accelerator* accelerator) {
NOTIMPLEMENTED();
return false;
}
bool RenderViewContextMenuImpl::IsCommandIdChecked(int command_id) const {
return false;
}
bool RenderViewContextMenuImpl::IsCommandIdEnabled(int command_id) const {
{
bool enabled = false;
if (RenderViewContextMenuBase::IsCommandIdKnown(command_id, &enabled))
return enabled;
}
switch (command_id) {
// Navigation
case CMD_BACK:
return source_web_contents_->GetController().CanGoBack();
case CMD_FORWARD:
return source_web_contents_->GetController().CanGoForward();
case CMD_RELOAD:
return true;
case CMD_VIEW_SOURCE:
return source_web_contents_->GetController().CanViewSource();
// Link
case CMD_OPEN_LINK_NEW_ACTIVITY:
return params_.link_url.is_valid();
// Editable
case CMD_UNDO:
return !!(params_.edit_flags & WebContextMenuData::CanUndo);
case CMD_REDO:
return !!(params_.edit_flags & WebContextMenuData::CanRedo);
case CMD_CUT:
return !!(params_.edit_flags & WebContextMenuData::CanCut);
case CMD_COPY:
return !!(params_.edit_flags & WebContextMenuData::CanCopy);
case CMD_PASTE:
case CMD_PASTE_AND_MATCH_STYLE:
return !!(params_.edit_flags & WebContextMenuData::CanPaste);
case CMD_DELETE:
return !!(params_.edit_flags & WebContextMenuData::CanDelete);
case CMD_SELECT_ALL:
return !!(params_.edit_flags & WebContextMenuData::CanSelectAll);
}
return false;
}
void RenderViewContextMenuImpl::ExecuteCommand(int command_id,
int event_flags) {
RenderViewContextMenuBase::ExecuteCommand(command_id, event_flags);
if (command_executed_)
return;
command_executed_ = true;
switch (command_id) {
// Navigation
case CMD_BACK:
source_web_contents_->GetController().GoBack();
break;
case CMD_FORWARD:
source_web_contents_->GetController().GoForward();
break;
case CMD_RELOAD:
source_web_contents_->GetController().Reload(true);
break;
case CMD_VIEW_SOURCE:
source_web_contents_->ViewSource();
break;
// Link
case CMD_OPEN_LINK_NEW_ACTIVITY:
OpenURL(
params_.link_url,
params_.frame_url.is_empty() ? params_.page_url : params_.frame_url,
NEW_FOREGROUND_TAB,
ui::PAGE_TRANSITION_LINK);
break;
// Editable
case CMD_UNDO:
source_web_contents_->Undo();
break;
case CMD_REDO:
source_web_contents_->Redo();
break;
case CMD_CUT:
source_web_contents_->Cut();
break;
case CMD_COPY:
source_web_contents_->Copy();
break;
case CMD_PASTE:
source_web_contents_->Paste();
break;
case CMD_PASTE_AND_MATCH_STYLE:
source_web_contents_->PasteAndMatchStyle();
break;
case CMD_DELETE:
source_web_contents_->Delete();
break;
case CMD_SELECT_ALL:
source_web_contents_->SelectAll();
break;
}
}
views::Widget* RenderViewContextMenuImpl::GetTopLevelWidget() {
return views::Widget::GetTopLevelWidgetForNativeView(GetActiveNativeView());
}
aura::Window* RenderViewContextMenuImpl::GetActiveNativeView() {
content::WebContents* web_contents =
content::WebContents::FromRenderFrameHost(GetRenderFrameHost());
if (!web_contents) {
LOG(ERROR) << "RenderViewContextMenuImpl::Show, couldn't find WebContents";
return NULL;
}
return web_contents->GetFullscreenRenderWidgetHostView()
? web_contents->GetFullscreenRenderWidgetHostView()
->GetNativeView()
: web_contents->GetNativeView();
}
} // namespace athena