Home | History | Annotate | Download | only in launcher
      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 "chrome/browser/ui/ash/launcher/launcher_context_menu.h"
      6 
      7 #include <string>
      8 
      9 #include "ash/desktop_background/user_wallpaper_delegate.h"
     10 #include "ash/root_window_controller.h"
     11 #include "ash/shell.h"
     12 #include "ash/shell_delegate.h"
     13 #include "ash/wm/property_util.h"
     14 #include "base/bind.h"
     15 #include "base/command_line.h"
     16 #include "base/prefs/pref_service.h"
     17 #include "chrome/browser/extensions/context_menu_matcher.h"
     18 #include "chrome/browser/extensions/extension_prefs.h"
     19 #include "chrome/browser/fullscreen.h"
     20 #include "chrome/browser/prefs/incognito_mode_prefs.h"
     21 #include "chrome/browser/profiles/profile.h"
     22 #include "chrome/browser/ui/ash/chrome_shell_delegate.h"
     23 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
     24 #include "chrome/common/chrome_switches.h"
     25 #include "content/public/common/context_menu_params.h"
     26 #include "grit/ash_strings.h"
     27 #include "grit/generated_resources.h"
     28 #include "ui/base/l10n/l10n_util.h"
     29 
     30 namespace {
     31 
     32 bool MenuItemHasLauncherContext(const extensions::MenuItem* item) {
     33   return item->contexts().Contains(extensions::MenuItem::LAUNCHER);
     34 }
     35 
     36 }  // namespace
     37 
     38 LauncherContextMenu::LauncherContextMenu(ChromeLauncherController* controller,
     39                                          const ash::LauncherItem* item,
     40                                          aura::RootWindow* root)
     41     : ui::SimpleMenuModel(NULL),
     42       controller_(controller),
     43       item_(*item),
     44       launcher_alignment_menu_(root),
     45       root_window_(root) {
     46   DCHECK(item);
     47   DCHECK(root_window_);
     48   Init();
     49 }
     50 
     51 LauncherContextMenu::LauncherContextMenu(ChromeLauncherController* controller,
     52                                          aura::RootWindow* root)
     53     : ui::SimpleMenuModel(NULL),
     54       controller_(controller),
     55       item_(ash::LauncherItem()),
     56       launcher_alignment_menu_(root),
     57       extension_items_(new extensions::ContextMenuMatcher(
     58           controller->profile(), this, this,
     59           base::Bind(MenuItemHasLauncherContext))),
     60       root_window_(root) {
     61   DCHECK(root_window_);
     62   Init();
     63 }
     64 
     65 void LauncherContextMenu::Init() {
     66   extension_items_.reset(new extensions::ContextMenuMatcher(
     67       controller_->profile(), this, this,
     68       base::Bind(MenuItemHasLauncherContext)));
     69   set_delegate(this);
     70 
     71   if (is_valid_item()) {
     72     if (item_.type == ash::TYPE_APP_SHORTCUT ||
     73         item_.type == ash::TYPE_WINDOWED_APP) {
     74       // V1 apps can be started from the menu - but V2 apps should not.
     75       if  (!controller_->IsPlatformApp(item_.id)) {
     76         AddItem(MENU_OPEN_NEW, string16());
     77         AddSeparator(ui::NORMAL_SEPARATOR);
     78       }
     79       AddItem(
     80           MENU_PIN,
     81           l10n_util::GetStringUTF16(controller_->IsPinned(item_.id) ?
     82                                     IDS_LAUNCHER_CONTEXT_MENU_UNPIN :
     83                                     IDS_LAUNCHER_CONTEXT_MENU_PIN));
     84       if (controller_->IsOpen(item_.id)) {
     85         AddItem(MENU_CLOSE,
     86                 l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_CLOSE));
     87       }
     88       if (!controller_->IsPlatformApp(item_.id) &&
     89           item_.type != ash::TYPE_WINDOWED_APP) {
     90         AddSeparator(ui::NORMAL_SEPARATOR);
     91         AddCheckItemWithStringId(
     92             LAUNCH_TYPE_REGULAR_TAB,
     93             IDS_APP_CONTEXT_MENU_OPEN_REGULAR);
     94         AddCheckItemWithStringId(
     95             LAUNCH_TYPE_PINNED_TAB,
     96             IDS_APP_CONTEXT_MENU_OPEN_PINNED);
     97         if (!ash::Shell::IsForcedMaximizeMode()) {
     98           AddCheckItemWithStringId(
     99               LAUNCH_TYPE_WINDOW,
    100               IDS_APP_CONTEXT_MENU_OPEN_WINDOW);
    101           // Even though the launch type is Full Screen it is more accurately
    102           // described as Maximized in Ash.
    103           AddCheckItemWithStringId(
    104               LAUNCH_TYPE_FULLSCREEN,
    105               IDS_APP_CONTEXT_MENU_OPEN_MAXIMIZED);
    106         }
    107       }
    108     } else if (item_.type == ash::TYPE_BROWSER_SHORTCUT) {
    109       AddItem(MENU_NEW_WINDOW,
    110               l10n_util::GetStringUTF16(IDS_LAUNCHER_NEW_WINDOW));
    111       if (!controller_->IsLoggedInAsGuest()) {
    112         AddItem(MENU_NEW_INCOGNITO_WINDOW,
    113                 l10n_util::GetStringUTF16(IDS_LAUNCHER_NEW_INCOGNITO_WINDOW));
    114       }
    115     } else {
    116       if (item_.type == ash::TYPE_PLATFORM_APP) {
    117         AddItem(
    118             MENU_PIN,
    119             l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_PIN));
    120       }
    121       if (controller_->IsOpen(item_.id)) {
    122         AddItem(MENU_CLOSE,
    123                 l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_CLOSE));
    124       }
    125     }
    126     AddSeparator(ui::NORMAL_SEPARATOR);
    127     if (item_.type == ash::TYPE_APP_SHORTCUT ||
    128         item_.type == ash::TYPE_WINDOWED_APP ||
    129         item_.type == ash::TYPE_PLATFORM_APP) {
    130       std::string app_id = controller_->GetAppIDForLauncherID(item_.id);
    131       if (!app_id.empty()) {
    132         int index = 0;
    133         extension_items_->AppendExtensionItems(
    134             app_id, string16(), &index);
    135         AddSeparator(ui::NORMAL_SEPARATOR);
    136       }
    137     }
    138   }
    139   // In fullscreen, the launcher is either hidden or autohidden depending on
    140   // the type of fullscreen. Do not show the auto-hide menu item while in
    141   // fullscreen because it is confusing when the preference appears not to
    142   // apply.
    143   if (!IsFullScreenMode()) {
    144     AddCheckItemWithStringId(MENU_AUTO_HIDE,
    145                              IDS_ASH_SHELF_CONTEXT_MENU_AUTO_HIDE);
    146   }
    147   if (CommandLine::ForCurrentProcess()->HasSwitch(
    148           switches::kShowShelfAlignmentMenu)) {
    149     AddSubMenuWithStringId(MENU_ALIGNMENT_MENU,
    150                            IDS_ASH_SHELF_CONTEXT_MENU_POSITION,
    151                            &launcher_alignment_menu_);
    152   }
    153 #if defined(OS_CHROMEOS)
    154   AddItem(MENU_CHANGE_WALLPAPER,
    155        l10n_util::GetStringUTF16(IDS_AURA_SET_DESKTOP_WALLPAPER));
    156 #endif
    157 }
    158 
    159 LauncherContextMenu::~LauncherContextMenu() {
    160 }
    161 
    162 bool LauncherContextMenu::IsItemForCommandIdDynamic(int command_id) const {
    163   return command_id == MENU_OPEN_NEW;
    164 }
    165 
    166 string16 LauncherContextMenu::GetLabelForCommandId(int command_id) const {
    167   if (command_id == MENU_OPEN_NEW) {
    168     if (item_.type == ash::TYPE_PLATFORM_APP) {
    169       return l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_NEW_WINDOW);
    170     }
    171     switch (controller_->GetLaunchType(item_.id)) {
    172       case extensions::ExtensionPrefs::LAUNCH_PINNED:
    173       case extensions::ExtensionPrefs::LAUNCH_REGULAR:
    174         return l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_NEW_TAB);
    175       case extensions::ExtensionPrefs::LAUNCH_FULLSCREEN:
    176       case extensions::ExtensionPrefs::LAUNCH_WINDOW:
    177         return l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_NEW_WINDOW);
    178     }
    179   }
    180   NOTREACHED();
    181   return string16();
    182 }
    183 
    184 bool LauncherContextMenu::IsCommandIdChecked(int command_id) const {
    185   switch (command_id) {
    186     case LAUNCH_TYPE_PINNED_TAB:
    187       return controller_->GetLaunchType(item_.id) ==
    188           extensions::ExtensionPrefs::LAUNCH_PINNED;
    189     case LAUNCH_TYPE_REGULAR_TAB:
    190       return controller_->GetLaunchType(item_.id) ==
    191           extensions::ExtensionPrefs::LAUNCH_REGULAR;
    192     case LAUNCH_TYPE_WINDOW:
    193       return controller_->GetLaunchType(item_.id) ==
    194           extensions::ExtensionPrefs::LAUNCH_WINDOW;
    195     case LAUNCH_TYPE_FULLSCREEN:
    196       return controller_->GetLaunchType(item_.id) ==
    197           extensions::ExtensionPrefs::LAUNCH_FULLSCREEN;
    198     case MENU_AUTO_HIDE:
    199       return controller_->GetShelfAutoHideBehavior(root_window_) ==
    200           ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS;
    201     default:
    202       return extension_items_->IsCommandIdChecked(command_id);
    203   }
    204 }
    205 
    206 bool LauncherContextMenu::IsCommandIdEnabled(int command_id) const {
    207   switch (command_id) {
    208     case MENU_PIN:
    209       return item_.type == ash::TYPE_PLATFORM_APP ||
    210           controller_->IsPinnable(item_.id);
    211 #if defined(OS_CHROMEOS)
    212     case MENU_CHANGE_WALLPAPER:
    213       return ash::Shell::GetInstance()->user_wallpaper_delegate()->
    214           CanOpenSetWallpaperPage();
    215 #endif
    216     case MENU_NEW_WINDOW:
    217       // "Normal" windows are not allowed when incognito is enforced.
    218       return IncognitoModePrefs::GetAvailability(
    219           controller_->profile()->GetPrefs()) != IncognitoModePrefs::FORCED;
    220     case MENU_AUTO_HIDE:
    221       return controller_->CanUserModifyShelfAutoHideBehavior(root_window_);
    222     case MENU_NEW_INCOGNITO_WINDOW:
    223       // Incognito windows are not allowed when incognito is disabled.
    224       return IncognitoModePrefs::GetAvailability(
    225           controller_->profile()->GetPrefs()) != IncognitoModePrefs::DISABLED;
    226     default:
    227       return extension_items_->IsCommandIdEnabled(command_id);
    228   }
    229 }
    230 
    231 bool LauncherContextMenu::GetAcceleratorForCommandId(
    232       int command_id,
    233       ui::Accelerator* accelerator) {
    234   return false;
    235 }
    236 
    237 void LauncherContextMenu::ExecuteCommand(int command_id, int event_flags) {
    238   switch (static_cast<MenuItem>(command_id)) {
    239     case MENU_OPEN_NEW:
    240       controller_->Launch(item_.id, ui::EF_NONE);
    241       break;
    242     case MENU_CLOSE:
    243       controller_->Close(item_.id);
    244       ChromeShellDelegate::instance()->RecordUserMetricsAction(
    245           ash::UMA_CLOSE_THROUGH_CONTEXT_MENU);
    246       break;
    247     case MENU_PIN:
    248       controller_->TogglePinned(item_.id);
    249       break;
    250     case LAUNCH_TYPE_PINNED_TAB:
    251       controller_->SetLaunchType(item_.id,
    252                                  extensions::ExtensionPrefs::LAUNCH_PINNED);
    253       break;
    254     case LAUNCH_TYPE_REGULAR_TAB:
    255       controller_->SetLaunchType(item_.id,
    256                                  extensions::ExtensionPrefs::LAUNCH_REGULAR);
    257       break;
    258     case LAUNCH_TYPE_WINDOW:
    259       controller_->SetLaunchType(item_.id,
    260                                  extensions::ExtensionPrefs::LAUNCH_WINDOW);
    261       break;
    262     case LAUNCH_TYPE_FULLSCREEN:
    263       controller_->SetLaunchType(item_.id,
    264                                  extensions::ExtensionPrefs::LAUNCH_FULLSCREEN);
    265       break;
    266     case MENU_AUTO_HIDE:
    267       controller_->ToggleShelfAutoHideBehavior(root_window_);
    268       break;
    269     case MENU_NEW_WINDOW:
    270       controller_->CreateNewWindow();
    271       break;
    272     case MENU_NEW_INCOGNITO_WINDOW:
    273       controller_->CreateNewIncognitoWindow();
    274       break;
    275     case MENU_ALIGNMENT_MENU:
    276       break;
    277 #if defined(OS_CHROMEOS)
    278     case MENU_CHANGE_WALLPAPER:
    279       ash::Shell::GetInstance()->user_wallpaper_delegate()->
    280           OpenSetWallpaperPage();
    281       break;
    282 #endif
    283     default:
    284       extension_items_->ExecuteCommand(command_id, NULL,
    285                                        content::ContextMenuParams());
    286   }
    287 }
    288