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.
5 #include "chrome/browser/ui/bookmarks/bookmark_context_menu_controller.h"
7 #include "base/command_line.h"
8 #include "base/compiler_specific.h"
9 #include "base/prefs/pref_service.h"
10 #include "chrome/app/chrome_command_ids.h"
11 #include "chrome/browser/bookmarks/bookmark_model.h"
12 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
13 #include "chrome/browser/bookmarks/bookmark_utils.h"
14 #include "chrome/browser/prefs/incognito_mode_prefs.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/ui/bookmarks/bookmark_editor.h"
17 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/chrome_pages.h"
20 #include "chrome/browser/ui/tabs/tab_strip_model.h"
21 #include "chrome/browser/undo/bookmark_undo_service.h"
22 #include "chrome/browser/undo/bookmark_undo_service_factory.h"
23 #include "chrome/common/chrome_switches.h"
24 #include "chrome/common/pref_names.h"
25 #include "content/public/browser/page_navigator.h"
26 #include "content/public/browser/user_metrics.h"
27 #include "grit/generated_resources.h"
28 #include "ui/base/l10n/l10n_util.h"
30 using base::UserMetricsAction
;
31 using content::PageNavigator
;
33 BookmarkContextMenuController::BookmarkContextMenuController(
34 gfx::NativeWindow parent_window
,
35 BookmarkContextMenuControllerDelegate
* delegate
,
38 PageNavigator
* navigator
,
39 const BookmarkNode
* parent
,
40 const std::vector
<const BookmarkNode
*>& selection
)
41 : parent_window_(parent_window
),
45 navigator_(navigator
),
47 selection_(selection
),
48 model_(BookmarkModelFactory::GetForProfile(profile
)) {
50 DCHECK(model_
->loaded());
51 menu_model_
.reset(new ui::SimpleMenuModel(this));
52 model_
->AddObserver(this);
57 BookmarkContextMenuController::~BookmarkContextMenuController() {
59 model_
->RemoveObserver(this);
62 void BookmarkContextMenuController::BuildMenu() {
63 if (selection_
.size() == 1 && selection_
[0]->is_url()) {
64 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL
,
65 IDS_BOOKMARK_BAR_OPEN_IN_NEW_TAB
);
66 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
,
67 IDS_BOOKMARK_BAR_OPEN_IN_NEW_WINDOW
);
68 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
,
69 IDS_BOOKMARK_BAR_OPEN_INCOGNITO
);
71 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL
, IDS_BOOKMARK_BAR_OPEN_ALL
);
72 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
,
73 IDS_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
);
74 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
,
75 IDS_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
);
79 if (selection_
.size() == 1 && selection_
[0]->is_folder()) {
80 AddItem(IDC_BOOKMARK_BAR_RENAME_FOLDER
, IDS_BOOKMARK_BAR_RENAME_FOLDER
);
82 AddItem(IDC_BOOKMARK_BAR_EDIT
, IDS_BOOKMARK_BAR_EDIT
);
86 AddItem(IDC_CUT
, IDS_CUT
);
87 AddItem(IDC_COPY
, IDS_COPY
);
88 AddItem(IDC_PASTE
, IDS_PASTE
);
91 AddItem(IDC_BOOKMARK_BAR_REMOVE
, IDS_BOOKMARK_BAR_REMOVE
);
92 if (CommandLine::ForCurrentProcess()->HasSwitch(
93 switches::kEnableBookmarkUndo
)) {
94 AddItem(IDC_BOOKMARK_BAR_UNDO
, IDS_BOOKMARK_BAR_UNDO
);
95 AddItem(IDC_BOOKMARK_BAR_REDO
, IDS_BOOKMARK_BAR_REDO
);
99 AddItem(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK
, IDS_BOOKMARK_BAR_ADD_NEW_BOOKMARK
);
100 AddItem(IDC_BOOKMARK_BAR_NEW_FOLDER
, IDS_BOOKMARK_BAR_NEW_FOLDER
);
103 AddItem(IDC_BOOKMARK_MANAGER
, IDS_BOOKMARK_MANAGER
);
104 // Use the native host desktop type in tests.
105 if (chrome::IsAppsShortcutEnabled(
107 browser_
? browser_
->host_desktop_type()
108 : chrome::HOST_DESKTOP_TYPE_NATIVE
)) {
109 AddCheckboxItem(IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
,
110 IDS_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
);
112 AddCheckboxItem(IDC_BOOKMARK_BAR_ALWAYS_SHOW
, IDS_SHOW_BOOKMARK_BAR
);
115 void BookmarkContextMenuController::AddItem(int id
, int localization_id
) {
116 menu_model_
->AddItemWithStringId(id
, localization_id
);
119 void BookmarkContextMenuController::AddSeparator() {
120 menu_model_
->AddSeparator(ui::NORMAL_SEPARATOR
);
123 void BookmarkContextMenuController::AddCheckboxItem(int id
,
124 int localization_id
) {
125 menu_model_
->AddCheckItemWithStringId(id
, localization_id
);
128 void BookmarkContextMenuController::ExecuteCommand(int id
, int event_flags
) {
130 delegate_
->WillExecuteCommand(id
, selection_
);
132 if (ExecutePlatformCommand(id
, event_flags
)) {
134 delegate_
->DidExecuteCommand(id
);
139 case IDC_BOOKMARK_BAR_OPEN_ALL
:
140 case IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
:
141 case IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
: {
142 WindowOpenDisposition initial_disposition
;
143 if (id
== IDC_BOOKMARK_BAR_OPEN_ALL
) {
144 initial_disposition
= NEW_BACKGROUND_TAB
;
145 content::RecordAction(
146 UserMetricsAction("BookmarkBar_ContextMenu_OpenAll"));
147 } else if (id
== IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
) {
148 initial_disposition
= NEW_WINDOW
;
149 content::RecordAction(
150 UserMetricsAction("BookmarkBar_ContextMenu_OpenAllInNewWindow"));
152 initial_disposition
= OFF_THE_RECORD
;
153 content::RecordAction(
154 UserMetricsAction("BookmarkBar_ContextMenu_OpenAllIncognito"));
156 chrome::OpenAll(parent_window_
, navigator_
, selection_
,
157 initial_disposition
, profile_
);
161 case IDC_BOOKMARK_BAR_RENAME_FOLDER
:
162 case IDC_BOOKMARK_BAR_EDIT
:
163 content::RecordAction(
164 UserMetricsAction("BookmarkBar_ContextMenu_Edit"));
166 if (selection_
.size() != 1) {
171 BookmarkEditor::Show(
174 BookmarkEditor::EditDetails::EditNode(selection_
[0]),
175 selection_
[0]->is_url() ? BookmarkEditor::SHOW_TREE
:
176 BookmarkEditor::NO_TREE
);
179 case IDC_BOOKMARK_BAR_UNDO
: {
180 content::RecordAction(
181 UserMetricsAction("BookmarkBar_ContextMenu_Undo"));
182 BookmarkUndoServiceFactory::GetForProfile(profile_
)->undo_manager()->
187 case IDC_BOOKMARK_BAR_REDO
: {
188 content::RecordAction(
189 UserMetricsAction("BookmarkBar_ContextMenu_Redo"));
190 BookmarkUndoServiceFactory::GetForProfile(profile_
)->undo_manager()->
195 case IDC_BOOKMARK_BAR_REMOVE
: {
196 content::RecordAction(
197 UserMetricsAction("BookmarkBar_ContextMenu_Remove"));
199 for (size_t i
= 0; i
< selection_
.size(); ++i
) {
200 int index
= selection_
[i
]->parent()->GetIndexOf(selection_
[i
]);
202 model_
->Remove(selection_
[i
]->parent(), index
);
208 case IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK
: {
209 content::RecordAction(
210 UserMetricsAction("BookmarkBar_ContextMenu_Add"));
213 const BookmarkNode
* parent
=
214 bookmark_utils::GetParentForNewNodes(parent_
, selection_
, &index
);
216 base::string16 title
;
217 chrome::GetURLAndTitleToBookmark(
218 browser_
->tab_strip_model()->GetActiveWebContents(),
220 BookmarkEditor::Show(parent_window_
,
222 BookmarkEditor::EditDetails::AddNodeInFolder(
223 parent
, index
, url
, title
),
224 BookmarkEditor::SHOW_TREE
);
228 case IDC_BOOKMARK_BAR_NEW_FOLDER
: {
229 content::RecordAction(
230 UserMetricsAction("BookmarkBar_ContextMenu_NewFolder"));
233 const BookmarkNode
* parent
=
234 bookmark_utils::GetParentForNewNodes(parent_
, selection_
, &index
);
235 BookmarkEditor::Show(
238 BookmarkEditor::EditDetails::AddFolder(parent
, index
),
239 BookmarkEditor::SHOW_TREE
);
243 case IDC_BOOKMARK_BAR_ALWAYS_SHOW
:
244 chrome::ToggleBookmarkBarWhenVisible(profile_
);
247 case IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
: {
248 PrefService
* prefs
= profile_
->GetPrefs();
250 prefs::kShowAppsShortcutInBookmarkBar
,
251 !prefs
->GetBoolean(prefs::kShowAppsShortcutInBookmarkBar
));
255 case IDC_BOOKMARK_MANAGER
: {
256 content::RecordAction(UserMetricsAction("ShowBookmarkManager"));
257 if (selection_
.size() != 1)
258 chrome::ShowBookmarkManager(browser_
);
259 else if (selection_
[0]->is_folder())
260 chrome::ShowBookmarkManagerForNode(browser_
, selection_
[0]->id());
262 chrome::ShowBookmarkManagerForNode(browser_
, parent_
->id());
264 chrome::ShowBookmarkManager(browser_
);
269 bookmark_utils::CopyToClipboard(model_
, selection_
, true);
273 bookmark_utils::CopyToClipboard(model_
, selection_
, false);
278 const BookmarkNode
* paste_target
=
279 bookmark_utils::GetParentForNewNodes(parent_
, selection_
, &index
);
283 bookmark_utils::PasteFromClipboard(model_
, paste_target
, index
);
292 delegate_
->DidExecuteCommand(id
);
295 bool BookmarkContextMenuController::IsItemForCommandIdDynamic(int command_id
)
297 return command_id
== IDC_BOOKMARK_BAR_UNDO
||
298 command_id
== IDC_BOOKMARK_BAR_REDO
;
301 base::string16
BookmarkContextMenuController::GetLabelForCommandId(
302 int command_id
) const {
303 if (command_id
== IDC_BOOKMARK_BAR_UNDO
) {
304 return BookmarkUndoServiceFactory::GetForProfile(profile_
)->
305 undo_manager()->GetUndoLabel();
307 if (command_id
== IDC_BOOKMARK_BAR_REDO
) {
308 return BookmarkUndoServiceFactory::GetForProfile(profile_
)->
309 undo_manager()->GetRedoLabel();
313 return base::string16();
316 bool BookmarkContextMenuController::IsCommandIdChecked(int command_id
) const {
317 PrefService
* prefs
= profile_
->GetPrefs();
318 if (command_id
== IDC_BOOKMARK_BAR_ALWAYS_SHOW
)
319 return prefs
->GetBoolean(prefs::kShowBookmarkBar
);
321 DCHECK_EQ(IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
, command_id
);
322 return prefs
->GetBoolean(prefs::kShowAppsShortcutInBookmarkBar
);
325 bool BookmarkContextMenuController::IsCommandIdEnabled(int command_id
) const {
326 bool enabled
= false;
327 if (IsPlatformCommandIdEnabled(command_id
, &enabled
))
330 PrefService
* prefs
= profile_
->GetPrefs();
332 bool is_root_node
= selection_
.size() == 1 &&
333 selection_
[0]->parent() == model_
->root_node();
334 bool can_edit
= prefs
->GetBoolean(prefs::kEditBookmarksEnabled
);
335 IncognitoModePrefs::Availability incognito_avail
=
336 IncognitoModePrefs::GetAvailability(prefs
);
337 switch (command_id
) {
338 case IDC_BOOKMARK_BAR_OPEN_INCOGNITO
:
339 return !profile_
->IsOffTheRecord() &&
340 incognito_avail
!= IncognitoModePrefs::DISABLED
;
342 case IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
:
343 return chrome::HasBookmarkURLsAllowedInIncognitoMode(selection_
, profile_
)
345 !profile_
->IsOffTheRecord() &&
346 incognito_avail
!= IncognitoModePrefs::DISABLED
;
348 case IDC_BOOKMARK_BAR_OPEN_ALL
:
349 return chrome::HasBookmarkURLs(selection_
);
350 case IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
:
351 return chrome::HasBookmarkURLs(selection_
) &&
352 incognito_avail
!= IncognitoModePrefs::FORCED
;
354 case IDC_BOOKMARK_BAR_RENAME_FOLDER
:
355 case IDC_BOOKMARK_BAR_EDIT
:
356 return selection_
.size() == 1 && !is_root_node
&& can_edit
;
358 case IDC_BOOKMARK_BAR_UNDO
:
360 BookmarkUndoServiceFactory::GetForProfile(profile_
)->
361 undo_manager()->undo_count() > 0;
363 case IDC_BOOKMARK_BAR_REDO
:
365 BookmarkUndoServiceFactory::GetForProfile(profile_
)->
366 undo_manager()->redo_count() > 0;
368 case IDC_BOOKMARK_BAR_REMOVE
:
369 return !selection_
.empty() && !is_root_node
&& can_edit
;
371 case IDC_BOOKMARK_BAR_NEW_FOLDER
:
372 case IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK
:
373 return can_edit
&& bookmark_utils::GetParentForNewNodes(
374 parent_
, selection_
, NULL
) != NULL
;
376 case IDC_BOOKMARK_BAR_ALWAYS_SHOW
:
377 return !prefs
->IsManagedPreference(prefs::kShowBookmarkBar
);
379 case IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
:
380 return !prefs
->IsManagedPreference(prefs::kShowAppsShortcutInBookmarkBar
);
384 return !selection_
.empty() && !is_root_node
&&
385 (command_id
== IDC_COPY
|| can_edit
);
388 // Paste to selection from the Bookmark Bar, to parent_ everywhere else
390 ((!selection_
.empty() &&
391 bookmark_utils::CanPasteFromClipboard(selection_
[0])) ||
392 bookmark_utils::CanPasteFromClipboard(parent_
));
397 bool BookmarkContextMenuController::GetAcceleratorForCommandId(
399 ui::Accelerator
* accelerator
) {
404 bool BookmarkContextMenuController::IsPlatformCommandIdEnabled(
406 bool* enabled
) const {
407 // By default, there are no platform-specific enabled or disabled commands.
411 bool BookmarkContextMenuController::ExecutePlatformCommand(int id
,
413 // By default, there are no platform-specific commands.
418 void BookmarkContextMenuController::BookmarkModelChanged() {
420 delegate_
->CloseMenu();