1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "athena/content/render_view_context_menu_impl.h"
7 #include "athena/strings/grit/athena_strings.h"
8 #include "components/renderer_context_menu/context_menu_content_type.h"
9 #include "components/renderer_context_menu/views/toolkit_delegate_views.h"
10 #include "content/public/browser/browser_context.h"
11 #include "content/public/browser/render_widget_host_view.h"
12 #include "content/public/browser/web_contents.h"
13 #include "third_party/WebKit/public/web/WebContextMenuData.h"
14 #include "ui/aura/client/screen_position_client.h"
15 #include "ui/aura/window.h"
16 #include "ui/base/l10n/l10n_util.h"
17 #include "ui/views/widget/widget.h"
20 using blink::WebContextMenuData;
32 CMD_OPEN_LINK_NEW_ACTIVITY,
40 CMD_PASTE_AND_MATCH_STYLE,
46 // Max number of custom command ids allowd.
47 const int kNumCustomCommandIds = 1000;
49 // TODO(oshima): Move IDS for context menus to components/renderer_context_menu
50 // and replace hardcoded strings below.
51 void AppendPageItems(ui::SimpleMenuModel* menu_model) {
52 menu_model->AddItem(CMD_BACK,
53 l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_BACK));
54 menu_model->AddItem(CMD_FORWARD,
55 l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_FORWARD));
56 menu_model->AddItem(CMD_RELOAD,
57 l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_RELOAD));
58 menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
61 l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_VIEWPAGESOURCE));
64 void AppendLinkItems(const content::ContextMenuParams& params,
65 ui::SimpleMenuModel* menu_model) {
66 if (!params.link_url.is_empty())
68 CMD_OPEN_LINK_NEW_ACTIVITY,
69 l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_OPENLINKNEWACTIVITY));
72 void AppendEditableItems(ui::SimpleMenuModel* menu_model) {
73 menu_model->AddItem(CMD_UNDO,
74 l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_UNDO));
75 menu_model->AddItem(CMD_REDO,
76 l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_REDO));
77 menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
78 menu_model->AddItem(CMD_CUT,
79 l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_CUT));
80 menu_model->AddItem(CMD_COPY,
81 l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_COPY));
82 menu_model->AddItem(CMD_PASTE,
83 l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_PASTE));
85 CMD_PASTE_AND_MATCH_STYLE,
86 l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_PASTE_AND_MATCH_STYLE));
87 menu_model->AddItem(CMD_DELETE,
88 l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_DELETE));
89 menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
90 menu_model->AddItem(CMD_SELECT_ALL,
91 l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_SELECTALL));
96 RenderViewContextMenuImpl::RenderViewContextMenuImpl(
97 content::RenderFrameHost* render_frame_host,
98 const content::ContextMenuParams& params)
99 : RenderViewContextMenuBase(render_frame_host, params) {
100 SetContentCustomCommandIdRange(CMD_LAST, CMD_LAST + kNumCustomCommandIds);
101 // TODO(oshima): Support other types
103 new ContextMenuContentType(source_web_contents_, params, true));
104 set_toolkit_delegate(scoped_ptr<ToolkitDelegate>(new ToolkitDelegateViews));
107 RenderViewContextMenuImpl::~RenderViewContextMenuImpl() {
110 void RenderViewContextMenuImpl::RunMenuAt(views::Widget* parent,
111 const gfx::Point& point,
112 ui::MenuSourceType type) {
113 static_cast<ToolkitDelegateViews*>(toolkit_delegate())
114 ->RunMenuAt(parent, point, type);
117 void RenderViewContextMenuImpl::Show() {
118 // Menus need a Widget to work. If we're not the active tab we won't
119 // necessarily be in a widget.
120 views::Widget* top_level_widget = GetTopLevelWidget();
121 if (!top_level_widget)
124 // Don't show empty menus.
125 if (menu_model().GetItemCount() == 0)
128 gfx::Point screen_point(params().x, params().y);
130 // Convert from target window coordinates to root window coordinates.
131 aura::Window* target_window = GetActiveNativeView();
132 aura::Window* root_window = target_window->GetRootWindow();
133 aura::client::ScreenPositionClient* screen_position_client =
134 aura::client::GetScreenPositionClient(root_window);
135 if (screen_position_client)
136 screen_position_client->ConvertPointToScreen(target_window, &screen_point);
138 // Enable recursive tasks on the message loop so we can get updates while
139 // the context menu is being displayed.
140 base::MessageLoop::ScopedNestableTaskAllower allow(
141 base::MessageLoop::current());
142 RunMenuAt(top_level_widget, screen_point, params().source_type);
145 void RenderViewContextMenuImpl::InitMenu() {
146 RenderViewContextMenuBase::InitMenu();
147 bool needs_separator = false;
148 if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_PAGE)) {
149 AppendPageItems(&menu_model_);
150 needs_separator = true;
153 if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_LINK)) {
156 AppendLinkItems(params_, &menu_model_);
157 needs_separator = true;
160 if (content_type_->SupportsGroup(
161 ContextMenuContentType::ITEM_GROUP_EDITABLE)) {
164 AppendEditableItems(&menu_model_);
168 void RenderViewContextMenuImpl::RecordShownItem(int id) {
169 // TODO(oshima): Imelement UMA stats. crbug.com/401673
173 void RenderViewContextMenuImpl::RecordUsedItem(int id) {
174 // TODO(oshima): Imelement UMA stats. crbug.com/401673
178 #if defined(ENABLE_PLUGINS)
179 void RenderViewContextMenuImpl::HandleAuthorizeAllPlugins() {
183 void RenderViewContextMenuImpl::NotifyMenuShown() {
186 void RenderViewContextMenuImpl::NotifyURLOpened(
188 content::WebContents* new_contents) {
191 bool RenderViewContextMenuImpl::GetAcceleratorForCommandId(
193 ui::Accelerator* accelerator) {
198 bool RenderViewContextMenuImpl::IsCommandIdChecked(int command_id) const {
202 bool RenderViewContextMenuImpl::IsCommandIdEnabled(int command_id) const {
204 bool enabled = false;
205 if (RenderViewContextMenuBase::IsCommandIdKnown(command_id, &enabled))
208 switch (command_id) {
211 return source_web_contents_->GetController().CanGoBack();
213 return source_web_contents_->GetController().CanGoForward();
216 case CMD_VIEW_SOURCE:
217 return source_web_contents_->GetController().CanViewSource();
220 case CMD_OPEN_LINK_NEW_ACTIVITY:
221 return params_.link_url.is_valid();
225 return !!(params_.edit_flags & WebContextMenuData::CanUndo);
228 return !!(params_.edit_flags & WebContextMenuData::CanRedo);
231 return !!(params_.edit_flags & WebContextMenuData::CanCut);
234 return !!(params_.edit_flags & WebContextMenuData::CanCopy);
237 case CMD_PASTE_AND_MATCH_STYLE:
238 return !!(params_.edit_flags & WebContextMenuData::CanPaste);
241 return !!(params_.edit_flags & WebContextMenuData::CanDelete);
244 return !!(params_.edit_flags & WebContextMenuData::CanSelectAll);
249 void RenderViewContextMenuImpl::ExecuteCommand(int command_id,
251 RenderViewContextMenuBase::ExecuteCommand(command_id, event_flags);
252 if (command_executed_)
254 command_executed_ = true;
255 switch (command_id) {
258 source_web_contents_->GetController().GoBack();
261 source_web_contents_->GetController().GoForward();
264 source_web_contents_->GetController().Reload(true);
266 case CMD_VIEW_SOURCE:
267 source_web_contents_->ViewSource();
271 case CMD_OPEN_LINK_NEW_ACTIVITY:
274 params_.frame_url.is_empty() ? params_.page_url : params_.frame_url,
276 ui::PAGE_TRANSITION_LINK);
281 source_web_contents_->Undo();
285 source_web_contents_->Redo();
289 source_web_contents_->Cut();
293 source_web_contents_->Copy();
297 source_web_contents_->Paste();
300 case CMD_PASTE_AND_MATCH_STYLE:
301 source_web_contents_->PasteAndMatchStyle();
305 source_web_contents_->Delete();
309 source_web_contents_->SelectAll();
314 views::Widget* RenderViewContextMenuImpl::GetTopLevelWidget() {
315 return views::Widget::GetTopLevelWidgetForNativeView(GetActiveNativeView());
318 aura::Window* RenderViewContextMenuImpl::GetActiveNativeView() {
319 content::WebContents* web_contents =
320 content::WebContents::FromRenderFrameHost(GetRenderFrameHost());
322 LOG(ERROR) << "RenderViewContextMenuImpl::Show, couldn't find WebContents";
326 return web_contents->GetFullscreenRenderWidgetHostView()
327 ? web_contents->GetFullscreenRenderWidgetHostView()
329 : web_contents->GetNativeView();
332 } // namespace athena