1// Copyright 2013 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 "content/shell/browser/shell_web_contents_view_delegate.h"
6
7#include "base/command_line.h"
8#include "content/public/browser/render_frame_host.h"
9#include "content/public/browser/render_process_host.h"
10#include "content/public/browser/render_view_host.h"
11#include "content/public/browser/render_widget_host_view.h"
12#include "content/public/browser/web_contents.h"
13#include "content/public/common/context_menu_params.h"
14#include "content/shell/browser/shell.h"
15#include "content/shell/browser/shell_browser_context.h"
16#include "content/shell/browser/shell_browser_main_parts.h"
17#include "content/shell/browser/shell_content_browser_client.h"
18#include "content/shell/browser/shell_devtools_frontend.h"
19#include "content/shell/browser/shell_web_contents_view_delegate_creator.h"
20#include "content/shell/common/shell_switches.h"
21#include "third_party/WebKit/public/web/WebContextMenuData.h"
22
23using blink::WebContextMenuData;
24
25namespace {
26
27enum {
28  ShellContextMenuItemCutId = 10001,
29  ShellContextMenuItemCopyId,
30  ShellContextMenuItemPasteId,
31  ShellContextMenuItemDeleteId,
32  ShellContextMenuItemOpenLinkId,
33  ShellContextMenuItemBackId,
34  ShellContextMenuItemForwardId,
35  ShellContextMenuItemReloadId,
36  ShellContextMenuItemInspectId
37};
38
39void MakeContextMenuItem(HMENU menu,
40                         int menu_index,
41                         LPCTSTR text,
42                         UINT id,
43                         bool enabled) {
44  MENUITEMINFO mii = {0};
45  mii.cbSize = sizeof(mii);
46  mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_DATA | MIIM_STRING | MIIM_STATE;
47  mii.fState = enabled ? MFS_ENABLED : (MF_DISABLED | MFS_GRAYED);
48  mii.fType = MFT_STRING;
49  mii.wID = id;
50  mii.dwTypeData = const_cast<LPTSTR>(text);
51
52  InsertMenuItem(menu, menu_index, TRUE, &mii);
53}
54
55}  // namespace
56
57namespace content {
58
59WebContentsViewDelegate* CreateShellWebContentsViewDelegate(
60    WebContents* web_contents) {
61  return new ShellWebContentsViewDelegate(web_contents);
62}
63
64ShellWebContentsViewDelegate::ShellWebContentsViewDelegate(
65    WebContents* web_contents)
66    : web_contents_(web_contents) {
67}
68
69ShellWebContentsViewDelegate::~ShellWebContentsViewDelegate() {
70}
71
72void ShellWebContentsViewDelegate::ShowContextMenu(
73    RenderFrameHost* render_frame_host,
74    const ContextMenuParams& params) {
75  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
76    return;
77
78  params_ = params;
79  bool has_link = !params_.unfiltered_link_url.is_empty();
80  bool has_selection = !params_.selection_text.empty();
81
82  HMENU menu = CreateMenu();
83  HMENU sub_menu = CreatePopupMenu();
84  AppendMenu(menu, MF_STRING | MF_POPUP, (UINT)sub_menu, L"");
85
86  int index = 0;
87  if (params_.media_type == WebContextMenuData::MediaTypeNone &&
88      !has_link &&
89      !has_selection &&
90      !params_.is_editable) {
91    MakeContextMenuItem(sub_menu,
92                        index++,
93                        L"Back",
94                        ShellContextMenuItemBackId,
95                        web_contents_->GetController().CanGoBack());
96
97    MakeContextMenuItem(sub_menu,
98                        index++,
99                        L"Forward",
100                        ShellContextMenuItemForwardId,
101                        web_contents_->GetController().CanGoForward());
102
103    MakeContextMenuItem(sub_menu,
104                        index++,
105                        L"Reload",
106                        ShellContextMenuItemReloadId,
107                        true);
108
109    AppendMenu(sub_menu, MF_SEPARATOR, 0, NULL);
110    index++;
111  }
112
113  if (has_link) {
114    MakeContextMenuItem(sub_menu,
115                        index++,
116                        L"Open in New Window",
117                        ShellContextMenuItemOpenLinkId,
118                        true);
119    AppendMenu(sub_menu, MF_SEPARATOR, 0, NULL);
120    index++;
121  }
122
123  if (params_.is_editable) {
124    bool cut_enabled = ((params_.edit_flags & WebContextMenuData::CanCut) != 0);
125    MakeContextMenuItem(sub_menu,
126                        index++,
127                        L"Cut",
128                        ShellContextMenuItemCutId,
129                        cut_enabled);
130
131    bool copy_enabled =
132        ((params_.edit_flags & WebContextMenuData::CanCopy) != 0);
133    MakeContextMenuItem(sub_menu,
134                        index++,
135                        L"Copy",
136                        ShellContextMenuItemCopyId,
137                        copy_enabled);
138
139    bool paste_enabled =
140        ((params_.edit_flags & WebContextMenuData::CanPaste) != 0);
141    MakeContextMenuItem(sub_menu,
142                        index++,
143                        L"Paste",
144                        ShellContextMenuItemPasteId,
145                        paste_enabled);
146    bool delete_enabled =
147        ((params_.edit_flags & WebContextMenuData::CanDelete) != 0);
148    MakeContextMenuItem(sub_menu,
149                        index++,
150                        L"Delete",
151                        ShellContextMenuItemDeleteId,
152                        delete_enabled);
153
154    AppendMenu(sub_menu, MF_SEPARATOR, 0, NULL);
155    index++;
156  } else if (has_selection) {
157    MakeContextMenuItem(sub_menu,
158                        index++,
159                        L"Copy",
160                        ShellContextMenuItemCopyId,
161                        true);
162
163    AppendMenu(sub_menu, MF_SEPARATOR, 0, NULL);
164    index++;
165  }
166
167  MakeContextMenuItem(sub_menu,
168                      index++,
169                      L"Inspect...",
170                      ShellContextMenuItemInspectId,
171                      true);
172#if defined(USE_AURA)
173  NOTIMPLEMENTED();
174#else
175  gfx::Point screen_point(params.x, params.y);
176  POINT point = screen_point.ToPOINT();
177  ClientToScreen(web_contents_->GetNativeView(), &point);
178
179  int selection =
180      TrackPopupMenu(sub_menu,
181                     TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
182                     point.x, point.y,
183                     0,
184                     web_contents_->GetContentNativeView(),
185                     NULL);
186
187  MenuItemSelected(selection);
188#endif
189  DestroyMenu(menu);
190}
191
192void ShellWebContentsViewDelegate::MenuItemSelected(int selection) {
193  switch (selection) {
194    case ShellContextMenuItemCutId:
195      web_contents_->Cut();
196      break;
197    case ShellContextMenuItemCopyId:
198      web_contents_->Copy();
199      break;
200    case ShellContextMenuItemPasteId:
201      web_contents_->Paste();
202      break;
203    case ShellContextMenuItemDeleteId:
204      web_contents_->Delete();
205      break;
206    case ShellContextMenuItemOpenLinkId: {
207      ShellBrowserContext* browser_context =
208          ShellContentBrowserClient::Get()->browser_context();
209      Shell::CreateNewWindow(browser_context,
210                             params_.link_url,
211                             NULL,
212                             MSG_ROUTING_NONE,
213                             gfx::Size());
214      break;
215    }
216    case ShellContextMenuItemBackId:
217      web_contents_->GetController().GoToOffset(-1);
218      web_contents_->Focus();
219      break;
220    case ShellContextMenuItemForwardId:
221      web_contents_->GetController().GoToOffset(1);
222      web_contents_->Focus();
223      break;
224    case ShellContextMenuItemReloadId:
225      web_contents_->GetController().Reload(false);
226      web_contents_->Focus();
227      break;
228    case ShellContextMenuItemInspectId: {
229      ShellDevToolsFrontend::Show(web_contents_);
230      break;
231    }
232  }
233}
234
235#if defined(TOOLKIT_VIEWS)
236void ShellWebContentsViewDelegate::ShowDisambiguationPopup(
237    const gfx::Rect& target_rect,
238    const SkBitmap& zoomed_bitmap,
239    const gfx::NativeView content,
240    const base::Callback<void(ui::GestureEvent*)>& gesture_cb,
241    const base::Callback<void(ui::MouseEvent*)>& mouse_cb) {
242}
243
244void ShellWebContentsViewDelegate::HideDisambiguationPopup() {
245}
246#endif
247
248}  // namespace content
249