launcher_context_menu.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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/shelf/shelf_widget.h"
12#include "ash/shell.h"
13#include "ash/shell_delegate.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
30namespace {
31
32bool MenuItemHasLauncherContext(const extensions::MenuItem* item) {
33  return item->contexts().Contains(extensions::MenuItem::LAUNCHER);
34}
35
36}  // namespace
37
38LauncherContextMenu::LauncherContextMenu(ChromeLauncherController* controller,
39                                         const ash::LauncherItem* item,
40                                         aura::RootWindow* root)
41    : ui::SimpleMenuModel(NULL),
42      controller_(controller),
43      item_(*item),
44      shelf_alignment_menu_(root),
45      root_window_(root) {
46  DCHECK(item);
47  DCHECK(root_window_);
48  Init();
49}
50
51LauncherContextMenu::LauncherContextMenu(ChromeLauncherController* controller,
52                                         aura::RootWindow* root)
53    : ui::SimpleMenuModel(NULL),
54      controller_(controller),
55      item_(ash::LauncherItem()),
56      shelf_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
65void 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        AddCheckItemWithStringId(
98            LAUNCH_TYPE_WINDOW,
99            IDS_APP_CONTEXT_MENU_OPEN_WINDOW);
100        // Even though the launch type is Full Screen it is more accurately
101        // described as Maximized in Ash.
102        AddCheckItemWithStringId(
103            LAUNCH_TYPE_FULLSCREEN,
104            IDS_APP_CONTEXT_MENU_OPEN_MAXIMIZED);
105      }
106    } else if (item_.type == ash::TYPE_BROWSER_SHORTCUT) {
107      AddItem(MENU_NEW_WINDOW,
108              l10n_util::GetStringUTF16(IDS_LAUNCHER_NEW_WINDOW));
109      if (!controller_->IsLoggedInAsGuest()) {
110        AddItem(MENU_NEW_INCOGNITO_WINDOW,
111                l10n_util::GetStringUTF16(IDS_LAUNCHER_NEW_INCOGNITO_WINDOW));
112      }
113    } else {
114      if (item_.type == ash::TYPE_PLATFORM_APP) {
115        AddItem(
116            MENU_PIN,
117            l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_PIN));
118      }
119      if (controller_->IsOpen(item_.id)) {
120        AddItem(MENU_CLOSE,
121                l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_CLOSE));
122      }
123    }
124    AddSeparator(ui::NORMAL_SEPARATOR);
125    if (item_.type == ash::TYPE_APP_SHORTCUT ||
126        item_.type == ash::TYPE_WINDOWED_APP ||
127        item_.type == ash::TYPE_PLATFORM_APP) {
128      std::string app_id = controller_->GetAppIDForLauncherID(item_.id);
129      if (!app_id.empty()) {
130        int index = 0;
131        extension_items_->AppendExtensionItems(
132            app_id, string16(), &index);
133        AddSeparator(ui::NORMAL_SEPARATOR);
134      }
135    }
136  }
137  // In fullscreen, the launcher is either hidden or autohidden depending on
138  // the type of fullscreen. Do not show the auto-hide menu item while in
139  // fullscreen because it is confusing when the preference appears not to
140  // apply.
141  if (!IsFullScreenMode()) {
142    AddCheckItemWithStringId(MENU_AUTO_HIDE,
143                             IDS_ASH_SHELF_CONTEXT_MENU_AUTO_HIDE);
144  }
145  if (ash::ShelfWidget::ShelfAlignmentAllowed()) {
146    AddSubMenuWithStringId(MENU_ALIGNMENT_MENU,
147                           IDS_ASH_SHELF_CONTEXT_MENU_POSITION,
148                           &shelf_alignment_menu_);
149  }
150#if defined(OS_CHROMEOS)
151  AddItem(MENU_CHANGE_WALLPAPER,
152       l10n_util::GetStringUTF16(IDS_AURA_SET_DESKTOP_WALLPAPER));
153#endif
154}
155
156LauncherContextMenu::~LauncherContextMenu() {
157}
158
159bool LauncherContextMenu::IsItemForCommandIdDynamic(int command_id) const {
160  return command_id == MENU_OPEN_NEW;
161}
162
163string16 LauncherContextMenu::GetLabelForCommandId(int command_id) const {
164  if (command_id == MENU_OPEN_NEW) {
165    if (item_.type == ash::TYPE_PLATFORM_APP) {
166      return l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_NEW_WINDOW);
167    }
168    switch (controller_->GetLaunchType(item_.id)) {
169      case extensions::ExtensionPrefs::LAUNCH_PINNED:
170      case extensions::ExtensionPrefs::LAUNCH_REGULAR:
171        return l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_NEW_TAB);
172      case extensions::ExtensionPrefs::LAUNCH_FULLSCREEN:
173      case extensions::ExtensionPrefs::LAUNCH_WINDOW:
174        return l10n_util::GetStringUTF16(IDS_LAUNCHER_CONTEXT_MENU_NEW_WINDOW);
175    }
176  }
177  NOTREACHED();
178  return string16();
179}
180
181bool LauncherContextMenu::IsCommandIdChecked(int command_id) const {
182  switch (command_id) {
183    case LAUNCH_TYPE_PINNED_TAB:
184      return controller_->GetLaunchType(item_.id) ==
185          extensions::ExtensionPrefs::LAUNCH_PINNED;
186    case LAUNCH_TYPE_REGULAR_TAB:
187      return controller_->GetLaunchType(item_.id) ==
188          extensions::ExtensionPrefs::LAUNCH_REGULAR;
189    case LAUNCH_TYPE_WINDOW:
190      return controller_->GetLaunchType(item_.id) ==
191          extensions::ExtensionPrefs::LAUNCH_WINDOW;
192    case LAUNCH_TYPE_FULLSCREEN:
193      return controller_->GetLaunchType(item_.id) ==
194          extensions::ExtensionPrefs::LAUNCH_FULLSCREEN;
195    case MENU_AUTO_HIDE:
196      return controller_->GetShelfAutoHideBehavior(root_window_) ==
197          ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS;
198    default:
199      return extension_items_->IsCommandIdChecked(command_id);
200  }
201}
202
203bool LauncherContextMenu::IsCommandIdEnabled(int command_id) const {
204  switch (command_id) {
205    case MENU_PIN:
206      return controller_->IsPinnable(item_.id);
207#if defined(OS_CHROMEOS)
208    case MENU_CHANGE_WALLPAPER:
209      return ash::Shell::GetInstance()->user_wallpaper_delegate()->
210          CanOpenSetWallpaperPage();
211#endif
212    case MENU_NEW_WINDOW:
213      // "Normal" windows are not allowed when incognito is enforced.
214      return IncognitoModePrefs::GetAvailability(
215          controller_->profile()->GetPrefs()) != IncognitoModePrefs::FORCED;
216    case MENU_AUTO_HIDE:
217      return controller_->CanUserModifyShelfAutoHideBehavior(root_window_);
218    case MENU_NEW_INCOGNITO_WINDOW:
219      // Incognito windows are not allowed when incognito is disabled.
220      return IncognitoModePrefs::GetAvailability(
221          controller_->profile()->GetPrefs()) != IncognitoModePrefs::DISABLED;
222    default:
223      return extension_items_->IsCommandIdEnabled(command_id);
224  }
225}
226
227bool LauncherContextMenu::GetAcceleratorForCommandId(
228      int command_id,
229      ui::Accelerator* accelerator) {
230  return false;
231}
232
233void LauncherContextMenu::ExecuteCommand(int command_id, int event_flags) {
234  switch (static_cast<MenuItem>(command_id)) {
235    case MENU_OPEN_NEW:
236      controller_->Launch(item_.id, ui::EF_NONE);
237      break;
238    case MENU_CLOSE:
239      controller_->Close(item_.id);
240      ChromeShellDelegate::instance()->RecordUserMetricsAction(
241          ash::UMA_CLOSE_THROUGH_CONTEXT_MENU);
242      break;
243    case MENU_PIN:
244      controller_->TogglePinned(item_.id);
245      break;
246    case LAUNCH_TYPE_PINNED_TAB:
247      controller_->SetLaunchType(item_.id,
248                                 extensions::ExtensionPrefs::LAUNCH_PINNED);
249      break;
250    case LAUNCH_TYPE_REGULAR_TAB:
251      controller_->SetLaunchType(item_.id,
252                                 extensions::ExtensionPrefs::LAUNCH_REGULAR);
253      break;
254    case LAUNCH_TYPE_WINDOW:
255      controller_->SetLaunchType(item_.id,
256                                 extensions::ExtensionPrefs::LAUNCH_WINDOW);
257      break;
258    case LAUNCH_TYPE_FULLSCREEN:
259      controller_->SetLaunchType(item_.id,
260                                 extensions::ExtensionPrefs::LAUNCH_FULLSCREEN);
261      break;
262    case MENU_AUTO_HIDE:
263      controller_->ToggleShelfAutoHideBehavior(root_window_);
264      break;
265    case MENU_NEW_WINDOW:
266      controller_->CreateNewWindow();
267      break;
268    case MENU_NEW_INCOGNITO_WINDOW:
269      controller_->CreateNewIncognitoWindow();
270      break;
271    case MENU_ALIGNMENT_MENU:
272      break;
273#if defined(OS_CHROMEOS)
274    case MENU_CHANGE_WALLPAPER:
275      ash::Shell::GetInstance()->user_wallpaper_delegate()->
276          OpenSetWallpaperPage();
277      break;
278#endif
279    default:
280      extension_items_->ExecuteCommand(command_id, NULL,
281                                       content::ContextMenuParams());
282  }
283}
284