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