Home | History | Annotate | Download | only in bookmarks
      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 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.h"
      6 
      7 #include "base/strings/sys_string_conversions.h"
      8 #include "chrome/app/chrome_command_ids.h"  // IDC_BOOKMARK_MENU
      9 #import "chrome/browser/app_controller_mac.h"
     10 #include "chrome/browser/bookmarks/bookmark_model.h"
     11 #include "chrome/browser/profiles/profile.h"
     12 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
     13 #include "chrome/browser/ui/browser.h"
     14 #include "chrome/browser/ui/browser_finder.h"
     15 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.h"
     16 #import "chrome/browser/ui/cocoa/l10n_util.h"
     17 #include "chrome/browser/ui/host_desktop.h"
     18 #include "content/public/browser/user_metrics.h"
     19 #import "ui/base/cocoa/cocoa_event_utils.h"
     20 #import "ui/base/cocoa/menu_controller.h"
     21 
     22 using content::OpenURLParams;
     23 using content::Referrer;
     24 using content::UserMetricsAction;
     25 
     26 namespace {
     27 
     28 // Menus more than this many pixels wide will get trimmed
     29 // TODO(jrg): ask UI dudes what a good value is.
     30 const NSUInteger kMaximumMenuPixelsWide = 300;
     31 
     32 }
     33 
     34 @implementation BookmarkMenuCocoaController
     35 
     36 + (NSString*)menuTitleForNode:(const BookmarkNode*)node {
     37   string16 title = [MenuController elideMenuTitle:node->GetTitle()
     38                                           toWidth:kMaximumMenuPixelsWide];
     39   return base::SysUTF16ToNSString(title);
     40 }
     41 
     42 + (NSString*)tooltipForNode:(const BookmarkNode*)node {
     43   NSString* title = base::SysUTF16ToNSString(node->GetTitle());
     44   std::string urlString = node->url().possibly_invalid_spec();
     45   NSString* url = base::SysUTF8ToNSString(urlString);
     46   return cocoa_l10n_util::TooltipForURLAndTitle(url, title);
     47 }
     48 
     49 - (id)initWithBridge:(BookmarkMenuBridge*)bridge
     50              andMenu:(NSMenu*)menu {
     51   if ((self = [super init])) {
     52     bridge_ = bridge;
     53     DCHECK(bridge_);
     54     menu_ = menu;
     55     [[self menu] setDelegate:self];
     56   }
     57   return self;
     58 }
     59 
     60 - (void)dealloc {
     61   if ([[self menu] delegate] == self)
     62     [[self menu] setDelegate:nil];
     63   [super dealloc];
     64 }
     65 
     66 - (NSMenu*)menu {
     67   return menu_;
     68 }
     69 
     70 - (BOOL)validateMenuItem:(NSMenuItem*)menuItem {
     71   AppController* controller = [NSApp delegate];
     72   return ![controller keyWindowIsModal];
     73 }
     74 
     75 // NSMenu delegate method: called just before menu is displayed.
     76 - (void)menuNeedsUpdate:(NSMenu*)menu {
     77   bridge_->UpdateMenu(menu);
     78 }
     79 
     80 // Return the a BookmarkNode that has the given id (called
     81 // "identifier" here to avoid conflict with objc's concept of "id").
     82 - (const BookmarkNode*)nodeForIdentifier:(int)identifier {
     83   return bridge_->GetBookmarkModel()->GetNodeByID(identifier);
     84 }
     85 
     86 // Open the URL of the given BookmarkNode in the current tab.
     87 - (void)openURLForNode:(const BookmarkNode*)node {
     88   Browser* browser =
     89       chrome::FindTabbedBrowser(bridge_->GetProfile(),
     90                                 true,
     91                                 chrome::HOST_DESKTOP_TYPE_NATIVE);
     92   if (!browser) {
     93     browser = new Browser(Browser::CreateParams(
     94         bridge_->GetProfile(), chrome::HOST_DESKTOP_TYPE_NATIVE));
     95   }
     96   WindowOpenDisposition disposition =
     97       ui::WindowOpenDispositionFromNSEvent([NSApp currentEvent]);
     98   OpenURLParams params(
     99       node->url(), Referrer(), disposition,
    100       content::PAGE_TRANSITION_AUTO_BOOKMARK, false);
    101   browser->OpenURL(params);
    102 }
    103 
    104 // Open sites under BookmarkNode with the specified disposition.
    105 - (void)openAll:(NSInteger)tag
    106     withDisposition:(WindowOpenDisposition)disposition {
    107   int identifier = tag;
    108 
    109   const BookmarkNode* node = [self nodeForIdentifier:identifier];
    110   DCHECK(node);
    111 
    112   Browser* browser =
    113       chrome::FindTabbedBrowser(bridge_->GetProfile(),
    114                                 true,
    115                                 chrome::HOST_DESKTOP_TYPE_NATIVE);
    116   if (!browser) {
    117     browser = new Browser(Browser::CreateParams(
    118         bridge_->GetProfile(), chrome::HOST_DESKTOP_TYPE_NATIVE));
    119   }
    120   DCHECK(browser);
    121 
    122   if (!node || !browser)
    123     return; // shouldn't be reached
    124 
    125   chrome::OpenAll(NULL, browser, node, disposition, browser->profile());
    126 
    127   if (disposition == NEW_FOREGROUND_TAB) {
    128     content::RecordAction(UserMetricsAction("OpenAllBookmarks"));
    129   } else if (disposition == NEW_WINDOW) {
    130     content::RecordAction(UserMetricsAction("OpenAllBookmarksNewWindow"));
    131   } else {
    132     content::RecordAction(
    133         UserMetricsAction("OpenAllBookmarksIncognitoWindow"));
    134   }
    135 }
    136 
    137 - (IBAction)openBookmarkMenuItem:(id)sender {
    138   NSInteger tag = [sender tag];
    139   int identifier = tag;
    140   const BookmarkNode* node = [self nodeForIdentifier:identifier];
    141   DCHECK(node);
    142   if (!node)
    143     return;  // shouldn't be reached
    144 
    145   [self openURLForNode:node];
    146 }
    147 
    148 - (IBAction)openAllBookmarks:(id)sender {
    149   [self openAll:[sender tag] withDisposition:NEW_FOREGROUND_TAB];
    150 }
    151 
    152 - (IBAction)openAllBookmarksNewWindow:(id)sender {
    153   [self openAll:[sender tag] withDisposition:NEW_WINDOW];
    154 }
    155 
    156 - (IBAction)openAllBookmarksIncognitoWindow:(id)sender {
    157   [self openAll:[sender tag] withDisposition:OFF_THE_RECORD];
    158 }
    159 
    160 @end  // BookmarkMenuCocoaController
    161