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/web_contents.h"
14#include "ui/base/accelerators/accelerator.h"
15#include "ui/base/l10n/l10n_util.h"
16#include "ui/events/keycodes/keyboard_codes.h"
17
18using content::WebContents;
19
20////////////////////////////////////////////////////////////////////////////////
21// RenderViewContextMenuViews, public:
22
23RenderViewContextMenuViews::RenderViewContextMenuViews(
24    content::RenderFrameHost* render_frame_host,
25    const content::ContextMenuParams& params)
26    : RenderViewContextMenu(render_frame_host, params),
27      bidi_submenu_model_(this) {
28  scoped_ptr<ToolkitDelegate> delegate(new ToolkitDelegateViews);
29  set_toolkit_delegate(delegate.Pass());
30}
31
32RenderViewContextMenuViews::~RenderViewContextMenuViews() {
33}
34
35// static
36RenderViewContextMenuViews* RenderViewContextMenuViews::Create(
37    content::RenderFrameHost* render_frame_host,
38    const content::ContextMenuParams& params) {
39  return new RenderViewContextMenuViews(render_frame_host, params);
40}
41
42void RenderViewContextMenuViews::RunMenuAt(views::Widget* parent,
43                                           const gfx::Point& point,
44                                           ui::MenuSourceType type) {
45  static_cast<ToolkitDelegateViews*>(toolkit_delegate())->
46      RunMenuAt(parent, point, type);
47}
48
49////////////////////////////////////////////////////////////////////////////////
50// RenderViewContextMenuViews, protected:
51
52bool RenderViewContextMenuViews::GetAcceleratorForCommandId(
53    int command_id,
54    ui::Accelerator* accel) {
55  // There are no formally defined accelerators we can query so we assume
56  // that Ctrl+C, Ctrl+V, Ctrl+X, Ctrl-A, etc do what they normally do.
57  switch (command_id) {
58    case IDC_CONTENT_CONTEXT_UNDO:
59      *accel = ui::Accelerator(ui::VKEY_Z, ui::EF_CONTROL_DOWN);
60      return true;
61
62    case IDC_CONTENT_CONTEXT_REDO:
63      // TODO(jcampan): should it be Ctrl-Y?
64      *accel = ui::Accelerator(ui::VKEY_Z,
65                               ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN);
66      return true;
67
68    case IDC_CONTENT_CONTEXT_CUT:
69      *accel = ui::Accelerator(ui::VKEY_X, ui::EF_CONTROL_DOWN);
70      return true;
71
72    case IDC_CONTENT_CONTEXT_COPY:
73      *accel = ui::Accelerator(ui::VKEY_C, ui::EF_CONTROL_DOWN);
74      return true;
75
76    case IDC_CONTENT_CONTEXT_PASTE:
77      *accel = ui::Accelerator(ui::VKEY_V, ui::EF_CONTROL_DOWN);
78      return true;
79
80    case IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE:
81      *accel = ui::Accelerator(ui::VKEY_V,
82                               ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN);
83      return true;
84
85    case IDC_CONTENT_CONTEXT_SELECTALL:
86      *accel = ui::Accelerator(ui::VKEY_A, ui::EF_CONTROL_DOWN);
87      return true;
88
89    default:
90      return false;
91  }
92}
93
94void RenderViewContextMenuViews::ExecuteCommand(int command_id,
95                                                int event_flags) {
96  switch (command_id) {
97    case IDC_WRITING_DIRECTION_DEFAULT:
98      // WebKit's current behavior is for this menu item to always be disabled.
99      NOTREACHED();
100      break;
101
102    case IDC_WRITING_DIRECTION_RTL:
103    case IDC_WRITING_DIRECTION_LTR: {
104      content::RenderViewHost* view_host = GetRenderViewHost();
105      view_host->UpdateTextDirection((command_id == IDC_WRITING_DIRECTION_RTL) ?
106          blink::WebTextDirectionRightToLeft :
107          blink::WebTextDirectionLeftToRight);
108      view_host->NotifyTextDirection();
109      break;
110    }
111
112    default:
113      RenderViewContextMenu::ExecuteCommand(command_id, event_flags);
114      break;
115  }
116}
117
118bool RenderViewContextMenuViews::IsCommandIdChecked(int command_id) const {
119  switch (command_id) {
120    case IDC_WRITING_DIRECTION_DEFAULT:
121      return (params_.writing_direction_default &
122          blink::WebContextMenuData::CheckableMenuItemChecked) != 0;
123    case IDC_WRITING_DIRECTION_RTL:
124      return (params_.writing_direction_right_to_left &
125          blink::WebContextMenuData::CheckableMenuItemChecked) != 0;
126    case IDC_WRITING_DIRECTION_LTR:
127      return (params_.writing_direction_left_to_right &
128          blink::WebContextMenuData::CheckableMenuItemChecked) != 0;
129
130    default:
131      return RenderViewContextMenu::IsCommandIdChecked(command_id);
132  }
133}
134
135bool RenderViewContextMenuViews::IsCommandIdEnabled(int command_id) const {
136  switch (command_id) {
137    case IDC_WRITING_DIRECTION_MENU:
138      return true;
139    case IDC_WRITING_DIRECTION_DEFAULT:  // Provided to match OS defaults.
140      return params_.writing_direction_default &
141          blink::WebContextMenuData::CheckableMenuItemEnabled;
142    case IDC_WRITING_DIRECTION_RTL:
143      return params_.writing_direction_right_to_left &
144          blink::WebContextMenuData::CheckableMenuItemEnabled;
145    case IDC_WRITING_DIRECTION_LTR:
146      return params_.writing_direction_left_to_right &
147          blink::WebContextMenuData::CheckableMenuItemEnabled;
148
149    default:
150      return RenderViewContextMenu::IsCommandIdEnabled(command_id);
151  }
152}
153
154void RenderViewContextMenuViews::AppendPlatformEditableItems() {
155  bidi_submenu_model_.AddCheckItem(
156      IDC_WRITING_DIRECTION_DEFAULT,
157      l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT));
158  bidi_submenu_model_.AddCheckItem(
159      IDC_WRITING_DIRECTION_LTR,
160      l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR));
161  bidi_submenu_model_.AddCheckItem(
162      IDC_WRITING_DIRECTION_RTL,
163      l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL));
164
165  menu_model_.AddSubMenu(
166      IDC_WRITING_DIRECTION_MENU,
167      l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_MENU),
168      &bidi_submenu_model_);
169}
170