1 // Copyright (c) 2012 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/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_process_host.h" 11 #include "content/public/browser/render_view_host.h" 12 #include "content/public/browser/render_widget_host_view.h" 13 #include "content/public/browser/web_contents.h" 14 #include "content/public/browser/web_contents_view.h" 15 #include "content/public/common/context_menu_params.h" 16 #include "content/shell/common/shell_switches.h" 17 #include "content/shell/shell.h" 18 #include "content/shell/shell_browser_context.h" 19 #include "content/shell/shell_browser_main_parts.h" 20 #include "content/shell/shell_content_browser_client.h" 21 #include "content/shell/shell_devtools_frontend.h" 22 #include "content/shell/shell_web_contents_view_delegate_creator.h" 23 #include "third_party/WebKit/public/web/WebContextMenuData.h" 24 25 using WebKit::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 const ContextMenuParams& params) { 97 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) 98 return; 99 100 params_ = params; 101 bool has_link = !params_.unfiltered_link_url.is_empty(); 102 bool has_selection = ! params_.selection_text.empty(); 103 104 NSMenu* menu = [[[NSMenu alloc] initWithTitle:@""] autorelease]; 105 ShellContextMenuDelegate* delegate = 106 [[ShellContextMenuDelegate alloc] initWithDelegate:this]; 107 [menu setDelegate:delegate]; 108 [menu setAutoenablesItems:NO]; 109 110 if (params.media_type == WebContextMenuData::MediaTypeNone && 111 !has_link && 112 !has_selection && 113 !params_.is_editable) { 114 BOOL back_menu_enabled = 115 web_contents_->GetController().CanGoBack() ? YES : NO; 116 MakeContextMenuItem(@"Back", 117 ShellContextMenuItemBackTag, 118 menu, 119 back_menu_enabled, 120 delegate); 121 122 BOOL forward_menu_enabled = 123 web_contents_->GetController().CanGoForward() ? YES : NO; 124 MakeContextMenuItem(@"Forward", 125 ShellContextMenuItemForwardTag, 126 menu, 127 forward_menu_enabled, 128 delegate); 129 130 MakeContextMenuItem(@"Reload", 131 ShellContextMenuItemReloadTag, 132 menu, 133 YES, 134 delegate); 135 136 NSMenuItem* separator = [NSMenuItem separatorItem]; 137 [menu addItem:separator]; 138 } 139 140 if (has_link) { 141 MakeContextMenuItem(@"Open In New Window", 142 ShellContextMenuItemOpenLinkTag, 143 menu, 144 YES, 145 delegate); 146 147 NSMenuItem* separator = [NSMenuItem separatorItem]; 148 [menu addItem:separator]; 149 } 150 151 if (params_.is_editable) { 152 BOOL cut_menu_enabled = 153 (params_.edit_flags & WebContextMenuData::CanCut) ? YES : NO; 154 MakeContextMenuItem(@"Cut", 155 ShellContextMenuItemCutTag, 156 menu, 157 cut_menu_enabled, 158 delegate); 159 160 BOOL copy_menu_enabled = 161 (params_.edit_flags & WebContextMenuData::CanCopy) ? YES : NO; 162 MakeContextMenuItem(@"Copy", 163 ShellContextMenuItemCopyTag, 164 menu, 165 copy_menu_enabled, 166 delegate); 167 168 BOOL paste_menu_enabled = 169 (params_.edit_flags & WebContextMenuData::CanPaste) ? YES : NO; 170 MakeContextMenuItem(@"Paste", 171 ShellContextMenuItemPasteTag, 172 menu, 173 paste_menu_enabled, 174 delegate); 175 176 BOOL delete_menu_enabled = 177 (params_.edit_flags & WebContextMenuData::CanDelete) ? YES : NO; 178 MakeContextMenuItem(@"Delete", 179 ShellContextMenuItemDeleteTag, 180 menu, 181 delete_menu_enabled, 182 delegate); 183 184 NSMenuItem* separator = [NSMenuItem separatorItem]; 185 [menu addItem:separator]; 186 } else if (has_selection) { 187 MakeContextMenuItem(@"Copy", 188 ShellContextMenuItemCopyTag, 189 menu, 190 YES, 191 delegate); 192 193 NSMenuItem* separator = [NSMenuItem separatorItem]; 194 [menu addItem:separator]; 195 } 196 197 MakeContextMenuItem(@"Inspect", 198 ShellContextMenuItemInspectTag, 199 menu, 200 YES, 201 delegate); 202 203 NSView* parent_view = web_contents_->GetView()->GetContentNativeView(); 204 NSEvent* currentEvent = [NSApp currentEvent]; 205 NSWindow* window = [parent_view window]; 206 NSPoint position = [window mouseLocationOutsideOfEventStream]; 207 NSTimeInterval eventTime = [currentEvent timestamp]; 208 NSEvent* clickEvent = [NSEvent mouseEventWithType:NSRightMouseDown 209 location:position 210 modifierFlags:NSRightMouseDownMask 211 timestamp:eventTime 212 windowNumber:[window windowNumber] 213 context:nil 214 eventNumber:0 215 clickCount:1 216 pressure:1.0]; 217 218 [NSMenu popUpContextMenu:menu 219 withEvent:clickEvent 220 forView:parent_view]; 221 } 222 223 void ShellWebContentsViewDelegate::ActionPerformed(int tag) { 224 switch (tag) { 225 case ShellContextMenuItemCutTag: 226 web_contents_->GetRenderViewHost()->Cut(); 227 break; 228 case ShellContextMenuItemCopyTag: 229 web_contents_->GetRenderViewHost()->Copy(); 230 break; 231 case ShellContextMenuItemPasteTag: 232 web_contents_->GetRenderViewHost()->Paste(); 233 break; 234 case ShellContextMenuItemDeleteTag: 235 web_contents_->GetRenderViewHost()->Delete(); 236 break; 237 case ShellContextMenuItemOpenLinkTag: { 238 ShellBrowserContext* browser_context = 239 ShellContentBrowserClient::Get()->browser_context(); 240 Shell::CreateNewWindow(browser_context, 241 params_.link_url, 242 NULL, 243 MSG_ROUTING_NONE, 244 gfx::Size()); 245 break; 246 } 247 case ShellContextMenuItemBackTag: 248 web_contents_->GetController().GoToOffset(-1); 249 web_contents_->GetView()->Focus(); 250 break; 251 case ShellContextMenuItemForwardTag: 252 web_contents_->GetController().GoToOffset(1); 253 web_contents_->GetView()->Focus(); 254 break; 255 case ShellContextMenuItemReloadTag: { 256 web_contents_->GetController().Reload(false); 257 web_contents_->GetView()->Focus(); 258 break; 259 } 260 case ShellContextMenuItemInspectTag: { 261 ShellDevToolsFrontend::Show(web_contents_); 262 break; 263 } 264 } 265 } 266 267 WebDragDestDelegate* ShellWebContentsViewDelegate::GetDragDestDelegate() { 268 return NULL; 269 } 270 271 NSObject<RenderWidgetHostViewMacDelegate>* 272 ShellWebContentsViewDelegate::CreateRenderWidgetHostViewDelegate( 273 content::RenderWidgetHost* render_widget_host) { 274 return NULL; 275 } 276 277 } // namespace content 278