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 #import <Cocoa/Cocoa.h> 8 9 #include "base/command_line.h" 10 #include "content/public/browser/render_frame_host.h" 11 #include "content/public/browser/render_process_host.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 "content/public/common/context_menu_params.h" 16 #include "content/shell/browser/shell.h" 17 #include "content/shell/browser/shell_browser_context.h" 18 #include "content/shell/browser/shell_browser_main_parts.h" 19 #include "content/shell/browser/shell_content_browser_client.h" 20 #include "content/shell/browser/shell_devtools_frontend.h" 21 #include "content/shell/browser/shell_web_contents_view_delegate_creator.h" 22 #include "content/shell/common/shell_switches.h" 23 #include "third_party/WebKit/public/web/WebContextMenuData.h" 24 25 using blink::WebContextMenuData; 26 27 enum { 28 ShellContextMenuItemCutTag = 0, 29 ShellContextMenuItemCopyTag, 30 ShellContextMenuItemPasteTag, 31 ShellContextMenuItemDeleteTag, 32 ShellContextMenuItemOpenLinkTag, 33 ShellContextMenuItemBackTag, 34 ShellContextMenuItemForwardTag, 35 ShellContextMenuItemReloadTag, 36 ShellContextMenuItemInspectTag 37 }; 38 39 @interface ShellContextMenuDelegate : NSObject<NSMenuDelegate> { 40 @private 41 content::ShellWebContentsViewDelegate* delegate_; 42 } 43 @end 44 45 @implementation ShellContextMenuDelegate 46 - (id)initWithDelegate:(content::ShellWebContentsViewDelegate*) delegate { 47 if ((self = [super init])) { 48 delegate_ = delegate; 49 } 50 return self; 51 } 52 53 - (void)itemSelected:(id)sender { 54 NSInteger tag = [sender tag]; 55 delegate_->ActionPerformed(tag); 56 } 57 @end 58 59 namespace { 60 61 NSMenuItem* MakeContextMenuItem(NSString* title, 62 NSInteger tag, 63 NSMenu* menu, 64 BOOL enabled, 65 ShellContextMenuDelegate* delegate) { 66 NSMenuItem* menu_item = 67 [[NSMenuItem alloc] initWithTitle:title 68 action:@selector(itemSelected:) 69 keyEquivalent:@""]; 70 [menu_item setTarget:delegate]; 71 [menu_item setTag:tag]; 72 [menu_item setEnabled:enabled]; 73 [menu addItem:menu_item]; 74 75 return menu_item; 76 } 77 78 } // namespace 79 80 namespace content { 81 82 WebContentsViewDelegate* CreateShellWebContentsViewDelegate( 83 WebContents* web_contents) { 84 return new ShellWebContentsViewDelegate(web_contents); 85 } 86 87 ShellWebContentsViewDelegate::ShellWebContentsViewDelegate( 88 WebContents* web_contents) 89 : web_contents_(web_contents) { 90 } 91 92 ShellWebContentsViewDelegate::~ShellWebContentsViewDelegate() { 93 } 94 95 void ShellWebContentsViewDelegate::ShowContextMenu( 96 RenderFrameHost* render_frame_host, 97 const ContextMenuParams& params) { 98 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) 99 return; 100 101 params_ = params; 102 bool has_link = !params_.unfiltered_link_url.is_empty(); 103 bool has_selection = ! params_.selection_text.empty(); 104 105 NSMenu* menu = [[[NSMenu alloc] initWithTitle:@""] autorelease]; 106 ShellContextMenuDelegate* delegate = 107 [[ShellContextMenuDelegate alloc] initWithDelegate:this]; 108 [menu setDelegate:delegate]; 109 [menu setAutoenablesItems:NO]; 110 111 if (params.media_type == WebContextMenuData::MediaTypeNone && 112 !has_link && 113 !has_selection && 114 !params_.is_editable) { 115 BOOL back_menu_enabled = 116 web_contents_->GetController().CanGoBack() ? YES : NO; 117 MakeContextMenuItem(@"Back", 118 ShellContextMenuItemBackTag, 119 menu, 120 back_menu_enabled, 121 delegate); 122 123 BOOL forward_menu_enabled = 124 web_contents_->GetController().CanGoForward() ? YES : NO; 125 MakeContextMenuItem(@"Forward", 126 ShellContextMenuItemForwardTag, 127 menu, 128 forward_menu_enabled, 129 delegate); 130 131 MakeContextMenuItem(@"Reload", 132 ShellContextMenuItemReloadTag, 133 menu, 134 YES, 135 delegate); 136 137 NSMenuItem* separator = [NSMenuItem separatorItem]; 138 [menu addItem:separator]; 139 } 140 141 if (has_link) { 142 MakeContextMenuItem(@"Open In New Window", 143 ShellContextMenuItemOpenLinkTag, 144 menu, 145 YES, 146 delegate); 147 148 NSMenuItem* separator = [NSMenuItem separatorItem]; 149 [menu addItem:separator]; 150 } 151 152 if (params_.is_editable) { 153 BOOL cut_menu_enabled = 154 (params_.edit_flags & WebContextMenuData::CanCut) ? YES : NO; 155 MakeContextMenuItem(@"Cut", 156 ShellContextMenuItemCutTag, 157 menu, 158 cut_menu_enabled, 159 delegate); 160 161 BOOL copy_menu_enabled = 162 (params_.edit_flags & WebContextMenuData::CanCopy) ? YES : NO; 163 MakeContextMenuItem(@"Copy", 164 ShellContextMenuItemCopyTag, 165 menu, 166 copy_menu_enabled, 167 delegate); 168 169 BOOL paste_menu_enabled = 170 (params_.edit_flags & WebContextMenuData::CanPaste) ? YES : NO; 171 MakeContextMenuItem(@"Paste", 172 ShellContextMenuItemPasteTag, 173 menu, 174 paste_menu_enabled, 175 delegate); 176 177 BOOL delete_menu_enabled = 178 (params_.edit_flags & WebContextMenuData::CanDelete) ? YES : NO; 179 MakeContextMenuItem(@"Delete", 180 ShellContextMenuItemDeleteTag, 181 menu, 182 delete_menu_enabled, 183 delegate); 184 185 NSMenuItem* separator = [NSMenuItem separatorItem]; 186 [menu addItem:separator]; 187 } else if (has_selection) { 188 MakeContextMenuItem(@"Copy", 189 ShellContextMenuItemCopyTag, 190 menu, 191 YES, 192 delegate); 193 194 NSMenuItem* separator = [NSMenuItem separatorItem]; 195 [menu addItem:separator]; 196 } 197 198 MakeContextMenuItem(@"Inspect", 199 ShellContextMenuItemInspectTag, 200 menu, 201 YES, 202 delegate); 203 204 NSView* parent_view = web_contents_->GetContentNativeView(); 205 NSEvent* currentEvent = [NSApp currentEvent]; 206 NSWindow* window = [parent_view window]; 207 NSPoint position = [window mouseLocationOutsideOfEventStream]; 208 NSTimeInterval eventTime = [currentEvent timestamp]; 209 NSEvent* clickEvent = [NSEvent mouseEventWithType:NSRightMouseDown 210 location:position 211 modifierFlags:NSRightMouseDownMask 212 timestamp:eventTime 213 windowNumber:[window windowNumber] 214 context:nil 215 eventNumber:0 216 clickCount:1 217 pressure:1.0]; 218 219 [NSMenu popUpContextMenu:menu 220 withEvent:clickEvent 221 forView:parent_view]; 222 } 223 224 void ShellWebContentsViewDelegate::ActionPerformed(int tag) { 225 switch (tag) { 226 case ShellContextMenuItemCutTag: 227 web_contents_->Cut(); 228 break; 229 case ShellContextMenuItemCopyTag: 230 web_contents_->Copy(); 231 break; 232 case ShellContextMenuItemPasteTag: 233 web_contents_->Paste(); 234 break; 235 case ShellContextMenuItemDeleteTag: 236 web_contents_->Delete(); 237 break; 238 case ShellContextMenuItemOpenLinkTag: { 239 ShellBrowserContext* browser_context = 240 ShellContentBrowserClient::Get()->browser_context(); 241 Shell::CreateNewWindow(browser_context, 242 params_.link_url, 243 NULL, 244 MSG_ROUTING_NONE, 245 gfx::Size()); 246 break; 247 } 248 case ShellContextMenuItemBackTag: 249 web_contents_->GetController().GoToOffset(-1); 250 web_contents_->Focus(); 251 break; 252 case ShellContextMenuItemForwardTag: 253 web_contents_->GetController().GoToOffset(1); 254 web_contents_->Focus(); 255 break; 256 case ShellContextMenuItemReloadTag: { 257 web_contents_->GetController().Reload(false); 258 web_contents_->Focus(); 259 break; 260 } 261 case ShellContextMenuItemInspectTag: { 262 ShellDevToolsFrontend::Show(web_contents_); 263 break; 264 } 265 } 266 } 267 268 } // namespace content 269