Home | History | Annotate | Download | only in browser
      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