Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / renderer_context_menu / render_view_context_menu_views.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 "chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.h"
6
7 #include "base/logging.h"
8 #include "base/strings/string16.h"
9 #include "chrome/app/chrome_command_ids.h"
10 #include "chrome/grit/generated_resources.h"
11 #include "components/renderer_context_menu/views/toolkit_delegate_views.h"
12 #include "content/public/browser/render_view_host.h"
13 #include "content/public/browser/render_widget_host_view.h"
14 #include "content/public/browser/web_contents.h"
15 #include "ui/aura/client/screen_position_client.h"
16 #include "ui/aura/window.h"
17 #include "ui/base/accelerators/accelerator.h"
18 #include "ui/base/l10n/l10n_util.h"
19 #include "ui/events/keycodes/keyboard_codes.h"
20 #include "ui/views/widget/widget.h"
21
22 using content::WebContents;
23
24 ////////////////////////////////////////////////////////////////////////////////
25 // RenderViewContextMenuViews, public:
26
27 RenderViewContextMenuViews::RenderViewContextMenuViews(
28     content::RenderFrameHost* render_frame_host,
29     const content::ContextMenuParams& params)
30     : RenderViewContextMenu(render_frame_host, params),
31       bidi_submenu_model_(this) {
32   scoped_ptr<ToolkitDelegate> delegate(new ToolkitDelegateViews);
33   set_toolkit_delegate(delegate.Pass());
34 }
35
36 RenderViewContextMenuViews::~RenderViewContextMenuViews() {
37 }
38
39 // static
40 RenderViewContextMenuViews* RenderViewContextMenuViews::Create(
41     content::RenderFrameHost* render_frame_host,
42     const content::ContextMenuParams& params) {
43   return new RenderViewContextMenuViews(render_frame_host, params);
44 }
45
46 void RenderViewContextMenuViews::RunMenuAt(views::Widget* parent,
47                                            const gfx::Point& point,
48                                            ui::MenuSourceType type) {
49   static_cast<ToolkitDelegateViews*>(toolkit_delegate())->
50       RunMenuAt(parent, point, type);
51 }
52
53 ////////////////////////////////////////////////////////////////////////////////
54 // RenderViewContextMenuViews, protected:
55
56 bool RenderViewContextMenuViews::GetAcceleratorForCommandId(
57     int command_id,
58     ui::Accelerator* accel) {
59   // There are no formally defined accelerators we can query so we assume
60   // that Ctrl+C, Ctrl+V, Ctrl+X, Ctrl-A, etc do what they normally do.
61   switch (command_id) {
62     case IDC_CONTENT_CONTEXT_UNDO:
63       *accel = ui::Accelerator(ui::VKEY_Z, ui::EF_CONTROL_DOWN);
64       return true;
65
66     case IDC_CONTENT_CONTEXT_REDO:
67       // TODO(jcampan): should it be Ctrl-Y?
68       *accel = ui::Accelerator(ui::VKEY_Z,
69                                ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN);
70       return true;
71
72     case IDC_CONTENT_CONTEXT_CUT:
73       *accel = ui::Accelerator(ui::VKEY_X, ui::EF_CONTROL_DOWN);
74       return true;
75
76     case IDC_CONTENT_CONTEXT_COPY:
77       *accel = ui::Accelerator(ui::VKEY_C, ui::EF_CONTROL_DOWN);
78       return true;
79
80     case IDC_CONTENT_CONTEXT_PASTE:
81       *accel = ui::Accelerator(ui::VKEY_V, ui::EF_CONTROL_DOWN);
82       return true;
83
84     case IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE:
85       *accel = ui::Accelerator(ui::VKEY_V,
86                                ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN);
87       return true;
88
89     case IDC_CONTENT_CONTEXT_SELECTALL:
90       *accel = ui::Accelerator(ui::VKEY_A, ui::EF_CONTROL_DOWN);
91       return true;
92
93     default:
94       return false;
95   }
96 }
97
98 void RenderViewContextMenuViews::ExecuteCommand(int command_id,
99                                                 int event_flags) {
100   switch (command_id) {
101     case IDC_WRITING_DIRECTION_DEFAULT:
102       // WebKit's current behavior is for this menu item to always be disabled.
103       NOTREACHED();
104       break;
105
106     case IDC_WRITING_DIRECTION_RTL:
107     case IDC_WRITING_DIRECTION_LTR: {
108       content::RenderViewHost* view_host = GetRenderViewHost();
109       view_host->UpdateTextDirection((command_id == IDC_WRITING_DIRECTION_RTL) ?
110           blink::WebTextDirectionRightToLeft :
111           blink::WebTextDirectionLeftToRight);
112       view_host->NotifyTextDirection();
113       break;
114     }
115
116     default:
117       RenderViewContextMenu::ExecuteCommand(command_id, event_flags);
118       break;
119   }
120 }
121
122 bool RenderViewContextMenuViews::IsCommandIdChecked(int command_id) const {
123   switch (command_id) {
124     case IDC_WRITING_DIRECTION_DEFAULT:
125       return (params_.writing_direction_default &
126           blink::WebContextMenuData::CheckableMenuItemChecked) != 0;
127     case IDC_WRITING_DIRECTION_RTL:
128       return (params_.writing_direction_right_to_left &
129           blink::WebContextMenuData::CheckableMenuItemChecked) != 0;
130     case IDC_WRITING_DIRECTION_LTR:
131       return (params_.writing_direction_left_to_right &
132           blink::WebContextMenuData::CheckableMenuItemChecked) != 0;
133
134     default:
135       return RenderViewContextMenu::IsCommandIdChecked(command_id);
136   }
137 }
138
139 bool RenderViewContextMenuViews::IsCommandIdEnabled(int command_id) const {
140   switch (command_id) {
141     case IDC_WRITING_DIRECTION_MENU:
142       return true;
143     case IDC_WRITING_DIRECTION_DEFAULT:  // Provided to match OS defaults.
144       return params_.writing_direction_default &
145           blink::WebContextMenuData::CheckableMenuItemEnabled;
146     case IDC_WRITING_DIRECTION_RTL:
147       return params_.writing_direction_right_to_left &
148           blink::WebContextMenuData::CheckableMenuItemEnabled;
149     case IDC_WRITING_DIRECTION_LTR:
150       return params_.writing_direction_left_to_right &
151           blink::WebContextMenuData::CheckableMenuItemEnabled;
152
153     default:
154       return RenderViewContextMenu::IsCommandIdEnabled(command_id);
155   }
156 }
157
158 void RenderViewContextMenuViews::AppendPlatformEditableItems() {
159   bidi_submenu_model_.AddCheckItem(
160       IDC_WRITING_DIRECTION_DEFAULT,
161       l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT));
162   bidi_submenu_model_.AddCheckItem(
163       IDC_WRITING_DIRECTION_LTR,
164       l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR));
165   bidi_submenu_model_.AddCheckItem(
166       IDC_WRITING_DIRECTION_RTL,
167       l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL));
168
169   menu_model_.AddSubMenu(
170       IDC_WRITING_DIRECTION_MENU,
171       l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_MENU),
172       &bidi_submenu_model_);
173 }
174
175 void RenderViewContextMenuViews::Show() {
176   // Menus need a Widget to work. If we're not the active tab we won't
177   // necessarily be in a widget.
178   views::Widget* top_level_widget = GetTopLevelWidget();
179   if (!top_level_widget)
180     return;
181
182   // Don't show empty menus.
183   if (menu_model().GetItemCount() == 0)
184     return;
185
186   gfx::Point screen_point(params().x, params().y);
187
188   // Convert from target window coordinates to root window coordinates.
189   aura::Window* target_window = GetActiveNativeView();
190   aura::Window* root_window = target_window->GetRootWindow();
191   aura::client::ScreenPositionClient* screen_position_client =
192       aura::client::GetScreenPositionClient(root_window);
193   if (screen_position_client) {
194     screen_position_client->ConvertPointToScreen(target_window, &screen_point);
195   }
196   // Enable recursive tasks on the message loop so we can get updates while
197   // the context menu is being displayed.
198   base::MessageLoop::ScopedNestableTaskAllower allow(
199       base::MessageLoop::current());
200   RunMenuAt(top_level_widget, screen_point, params().source_type);
201 }
202
203 views::Widget* RenderViewContextMenuViews::GetTopLevelWidget() {
204   return views::Widget::GetTopLevelWidgetForNativeView(GetActiveNativeView());
205 }
206
207 aura::Window* RenderViewContextMenuViews::GetActiveNativeView() {
208   WebContents* web_contents =
209       WebContents::FromRenderFrameHost(GetRenderFrameHost());
210   if (!web_contents) {
211     LOG(ERROR) << "RenderViewContextMenuViews::Show, couldn't find WebContents";
212     return NULL;
213   }
214   return web_contents->GetFullscreenRenderWidgetHostView()
215              ? web_contents->GetFullscreenRenderWidgetHostView()
216                    ->GetNativeView()
217              : web_contents->GetNativeView();
218 }