Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / athena / content / render_view_context_menu_impl.cc
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.
4
5 #include "athena/content/render_view_context_menu_impl.h"
6
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"
18
19 namespace athena {
20 using blink::WebContextMenuData;
21
22 namespace {
23
24 enum {
25   // Nativation
26   CMD_BACK = 0,
27   CMD_FORWARD,
28   CMD_RELOAD,
29   CMD_VIEW_SOURCE,
30
31   // Link
32   CMD_OPEN_LINK_NEW_ACTIVITY,
33
34   // Edit
35   CMD_UNDO,
36   CMD_REDO,
37   CMD_CUT,
38   CMD_COPY,
39   CMD_PASTE,
40   CMD_PASTE_AND_MATCH_STYLE,
41   CMD_DELETE,
42   CMD_SELECT_ALL,
43   CMD_LAST,
44 };
45
46 // Max number of custom command ids allowd.
47 const int kNumCustomCommandIds = 1000;
48
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);
59   menu_model->AddItem(
60       CMD_VIEW_SOURCE,
61       l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_VIEWPAGESOURCE));
62 }
63
64 void AppendLinkItems(const content::ContextMenuParams& params,
65                      ui::SimpleMenuModel* menu_model) {
66   if (!params.link_url.is_empty())
67     menu_model->AddItem(
68         CMD_OPEN_LINK_NEW_ACTIVITY,
69         l10n_util::GetStringUTF16(IDS_ATHENA_CONTEXT_OPENLINKNEWACTIVITY));
70 }
71
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));
84   menu_model->AddItem(
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));
92 }
93
94 }  // namespace
95
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
102   set_content_type(
103       new ContextMenuContentType(source_web_contents_, params, true));
104   set_toolkit_delegate(scoped_ptr<ToolkitDelegate>(new ToolkitDelegateViews));
105 }
106
107 RenderViewContextMenuImpl::~RenderViewContextMenuImpl() {
108 }
109
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);
115 }
116
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)
122     return;
123
124   // Don't show empty menus.
125   if (menu_model().GetItemCount() == 0)
126     return;
127
128   gfx::Point screen_point(params().x, params().y);
129
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);
137
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);
143 }
144
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;
151   }
152
153   if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_LINK)) {
154     if (needs_separator)
155       AddSeparator();
156     AppendLinkItems(params_, &menu_model_);
157     needs_separator = true;
158   }
159
160   if (content_type_->SupportsGroup(
161           ContextMenuContentType::ITEM_GROUP_EDITABLE)) {
162     if (needs_separator)
163       AddSeparator();
164     AppendEditableItems(&menu_model_);
165   }
166 }
167
168 void RenderViewContextMenuImpl::RecordShownItem(int id) {
169   // TODO(oshima): Imelement UMA stats. crbug.com/401673
170   NOTIMPLEMENTED();
171 }
172
173 void RenderViewContextMenuImpl::RecordUsedItem(int id) {
174   // TODO(oshima): Imelement UMA stats. crbug.com/401673
175   NOTIMPLEMENTED();
176 }
177
178 #if defined(ENABLE_PLUGINS)
179 void RenderViewContextMenuImpl::HandleAuthorizeAllPlugins() {
180 }
181 #endif
182
183 void RenderViewContextMenuImpl::NotifyMenuShown() {
184 }
185
186 void RenderViewContextMenuImpl::NotifyURLOpened(
187     const GURL& url,
188     content::WebContents* new_contents) {
189 }
190
191 bool RenderViewContextMenuImpl::GetAcceleratorForCommandId(
192     int command_id,
193     ui::Accelerator* accelerator) {
194   NOTIMPLEMENTED();
195   return false;
196 }
197
198 bool RenderViewContextMenuImpl::IsCommandIdChecked(int command_id) const {
199   return false;
200 }
201
202 bool RenderViewContextMenuImpl::IsCommandIdEnabled(int command_id) const {
203   {
204     bool enabled = false;
205     if (RenderViewContextMenuBase::IsCommandIdKnown(command_id, &enabled))
206       return enabled;
207   }
208   switch (command_id) {
209     // Navigation
210     case CMD_BACK:
211       return source_web_contents_->GetController().CanGoBack();
212     case CMD_FORWARD:
213       return source_web_contents_->GetController().CanGoForward();
214     case CMD_RELOAD:
215       return true;
216     case CMD_VIEW_SOURCE:
217       return source_web_contents_->GetController().CanViewSource();
218
219     // Link
220     case CMD_OPEN_LINK_NEW_ACTIVITY:
221       return params_.link_url.is_valid();
222
223     // Editable
224     case CMD_UNDO:
225       return !!(params_.edit_flags & WebContextMenuData::CanUndo);
226
227     case CMD_REDO:
228       return !!(params_.edit_flags & WebContextMenuData::CanRedo);
229
230     case CMD_CUT:
231       return !!(params_.edit_flags & WebContextMenuData::CanCut);
232
233     case CMD_COPY:
234       return !!(params_.edit_flags & WebContextMenuData::CanCopy);
235
236     case CMD_PASTE:
237     case CMD_PASTE_AND_MATCH_STYLE:
238       return !!(params_.edit_flags & WebContextMenuData::CanPaste);
239
240     case CMD_DELETE:
241       return !!(params_.edit_flags & WebContextMenuData::CanDelete);
242
243     case CMD_SELECT_ALL:
244       return !!(params_.edit_flags & WebContextMenuData::CanSelectAll);
245   }
246   return false;
247 }
248
249 void RenderViewContextMenuImpl::ExecuteCommand(int command_id,
250                                                int event_flags) {
251   RenderViewContextMenuBase::ExecuteCommand(command_id, event_flags);
252   if (command_executed_)
253     return;
254   command_executed_ = true;
255   switch (command_id) {
256     // Navigation
257     case CMD_BACK:
258       source_web_contents_->GetController().GoBack();
259       break;
260     case CMD_FORWARD:
261       source_web_contents_->GetController().GoForward();
262       break;
263     case CMD_RELOAD:
264       source_web_contents_->GetController().Reload(true);
265       break;
266     case CMD_VIEW_SOURCE:
267       source_web_contents_->ViewSource();
268       break;
269
270     // Link
271     case CMD_OPEN_LINK_NEW_ACTIVITY:
272       OpenURL(
273           params_.link_url,
274           params_.frame_url.is_empty() ? params_.page_url : params_.frame_url,
275           NEW_FOREGROUND_TAB,
276           ui::PAGE_TRANSITION_LINK);
277       break;
278
279     // Editable
280     case CMD_UNDO:
281       source_web_contents_->Undo();
282       break;
283
284     case CMD_REDO:
285       source_web_contents_->Redo();
286       break;
287
288     case CMD_CUT:
289       source_web_contents_->Cut();
290       break;
291
292     case CMD_COPY:
293       source_web_contents_->Copy();
294       break;
295
296     case CMD_PASTE:
297       source_web_contents_->Paste();
298       break;
299
300     case CMD_PASTE_AND_MATCH_STYLE:
301       source_web_contents_->PasteAndMatchStyle();
302       break;
303
304     case CMD_DELETE:
305       source_web_contents_->Delete();
306       break;
307
308     case CMD_SELECT_ALL:
309       source_web_contents_->SelectAll();
310       break;
311   }
312 }
313
314 views::Widget* RenderViewContextMenuImpl::GetTopLevelWidget() {
315   return views::Widget::GetTopLevelWidgetForNativeView(GetActiveNativeView());
316 }
317
318 aura::Window* RenderViewContextMenuImpl::GetActiveNativeView() {
319   content::WebContents* web_contents =
320       content::WebContents::FromRenderFrameHost(GetRenderFrameHost());
321   if (!web_contents) {
322     LOG(ERROR) << "RenderViewContextMenuImpl::Show, couldn't find WebContents";
323     return NULL;
324   }
325
326   return web_contents->GetFullscreenRenderWidgetHostView()
327              ? web_contents->GetFullscreenRenderWidgetHostView()
328                    ->GetNativeView()
329              : web_contents->GetNativeView();
330 }
331
332 }  // namespace athena