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_factory.h"
12 #include "chrome/browser/bookmarks/managed_bookmark_service_factory.h"
13 #include "chrome/browser/prefs/incognito_mode_prefs.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/bookmarks/bookmark_editor.h"
16 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/chrome_pages.h"
19 #include "chrome/browser/ui/tabs/tab_strip_model.h"
20 #include "chrome/browser/undo/bookmark_undo_service_factory.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "chrome/common/pref_names.h"
23 #include "chrome/grit/generated_resources.h"
24 #include "components/bookmarks/browser/bookmark_client.h"
25 #include "components/bookmarks/browser/bookmark_model.h"
26 #include "components/bookmarks/browser/bookmark_utils.h"
27 #include "components/bookmarks/managed/managed_bookmark_service.h"
28 #include "components/undo/bookmark_undo_service.h"
29 #include "content/public/browser/page_navigator.h"
30 #include "content/public/browser/user_metrics.h"
31 #include "grit/components_strings.h"
32 #include "ui/base/l10n/l10n_util.h"
34 using base::UserMetricsAction
;
35 using bookmarks::BookmarkNode
;
36 using content::PageNavigator
;
38 BookmarkContextMenuController::BookmarkContextMenuController(
39 gfx::NativeWindow parent_window
,
40 BookmarkContextMenuControllerDelegate
* delegate
,
43 PageNavigator
* navigator
,
44 const BookmarkNode
* parent
,
45 const std::vector
<const BookmarkNode
*>& selection
)
46 : parent_window_(parent_window
),
50 navigator_(navigator
),
52 selection_(selection
),
53 model_(BookmarkModelFactory::GetForProfile(profile
)) {
55 DCHECK(model_
->loaded());
56 menu_model_
.reset(new ui::SimpleMenuModel(this));
57 model_
->AddObserver(this);
62 BookmarkContextMenuController::~BookmarkContextMenuController() {
64 model_
->RemoveObserver(this);
67 void BookmarkContextMenuController::BuildMenu() {
68 if (selection_
.size() == 1 && selection_
[0]->is_url()) {
69 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL
,
70 IDS_BOOKMARK_BAR_OPEN_IN_NEW_TAB
);
71 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
,
72 IDS_BOOKMARK_BAR_OPEN_IN_NEW_WINDOW
);
73 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
,
74 IDS_BOOKMARK_BAR_OPEN_INCOGNITO
);
76 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL
, IDS_BOOKMARK_BAR_OPEN_ALL
);
77 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
,
78 IDS_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
);
79 AddItem(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
,
80 IDS_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
);
84 if (selection_
.size() == 1 && selection_
[0]->is_folder()) {
85 AddItem(IDC_BOOKMARK_BAR_RENAME_FOLDER
, IDS_BOOKMARK_BAR_RENAME_FOLDER
);
87 AddItem(IDC_BOOKMARK_BAR_EDIT
, IDS_BOOKMARK_BAR_EDIT
);
91 AddItem(IDC_CUT
, IDS_CUT
);
92 AddItem(IDC_COPY
, IDS_COPY
);
93 AddItem(IDC_PASTE
, IDS_PASTE
);
96 AddItem(IDC_BOOKMARK_BAR_REMOVE
, IDS_BOOKMARK_BAR_REMOVE
);
97 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
98 switches::kEnableBookmarkUndo
)) {
99 AddItem(IDC_BOOKMARK_BAR_UNDO
, IDS_BOOKMARK_BAR_UNDO
);
100 AddItem(IDC_BOOKMARK_BAR_REDO
, IDS_BOOKMARK_BAR_REDO
);
104 AddItem(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK
, IDS_BOOKMARK_BAR_ADD_NEW_BOOKMARK
);
105 AddItem(IDC_BOOKMARK_BAR_NEW_FOLDER
, IDS_BOOKMARK_BAR_NEW_FOLDER
);
108 AddItem(IDC_BOOKMARK_MANAGER
, IDS_BOOKMARK_MANAGER
);
109 // Use the native host desktop type in tests.
110 if (chrome::IsAppsShortcutEnabled(
112 browser_
? browser_
->host_desktop_type()
113 : chrome::HOST_DESKTOP_TYPE_NATIVE
)) {
114 AddCheckboxItem(IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
,
115 IDS_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
);
117 AddCheckboxItem(IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
,
118 IDS_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS_DEFAULT_NAME
);
119 AddCheckboxItem(IDC_BOOKMARK_BAR_ALWAYS_SHOW
, IDS_SHOW_BOOKMARK_BAR
);
122 void BookmarkContextMenuController::AddItem(int id
, int localization_id
) {
123 menu_model_
->AddItemWithStringId(id
, localization_id
);
126 void BookmarkContextMenuController::AddSeparator() {
127 menu_model_
->AddSeparator(ui::NORMAL_SEPARATOR
);
130 void BookmarkContextMenuController::AddCheckboxItem(int id
,
131 int localization_id
) {
132 menu_model_
->AddCheckItemWithStringId(id
, localization_id
);
135 void BookmarkContextMenuController::ExecuteCommand(int id
, int event_flags
) {
137 delegate_
->WillExecuteCommand(id
, selection_
);
140 case IDC_BOOKMARK_BAR_OPEN_ALL
:
141 case IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
:
142 case IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
: {
143 WindowOpenDisposition initial_disposition
;
144 if (id
== IDC_BOOKMARK_BAR_OPEN_ALL
) {
145 initial_disposition
= NEW_BACKGROUND_TAB
;
146 content::RecordAction(
147 UserMetricsAction("BookmarkBar_ContextMenu_OpenAll"));
148 } else if (id
== IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
) {
149 initial_disposition
= NEW_WINDOW
;
150 content::RecordAction(
151 UserMetricsAction("BookmarkBar_ContextMenu_OpenAllInNewWindow"));
153 initial_disposition
= OFF_THE_RECORD
;
154 content::RecordAction(
155 UserMetricsAction("BookmarkBar_ContextMenu_OpenAllIncognito"));
157 chrome::OpenAll(parent_window_
, navigator_
, selection_
,
158 initial_disposition
, profile_
);
162 case IDC_BOOKMARK_BAR_RENAME_FOLDER
:
163 case IDC_BOOKMARK_BAR_EDIT
:
164 content::RecordAction(
165 UserMetricsAction("BookmarkBar_ContextMenu_Edit"));
167 if (selection_
.size() != 1) {
172 BookmarkEditor::Show(
175 BookmarkEditor::EditDetails::EditNode(selection_
[0]),
176 selection_
[0]->is_url() ? BookmarkEditor::SHOW_TREE
:
177 BookmarkEditor::NO_TREE
);
180 case IDC_BOOKMARK_BAR_UNDO
: {
181 content::RecordAction(
182 UserMetricsAction("BookmarkBar_ContextMenu_Undo"));
183 BookmarkUndoServiceFactory::GetForProfile(profile_
)->undo_manager()->
188 case IDC_BOOKMARK_BAR_REDO
: {
189 content::RecordAction(
190 UserMetricsAction("BookmarkBar_ContextMenu_Redo"));
191 BookmarkUndoServiceFactory::GetForProfile(profile_
)->undo_manager()->
196 case IDC_BOOKMARK_BAR_REMOVE
: {
197 content::RecordAction(
198 UserMetricsAction("BookmarkBar_ContextMenu_Remove"));
200 for (size_t i
= 0; i
< selection_
.size(); ++i
) {
201 int index
= selection_
[i
]->parent()->GetIndexOf(selection_
[i
]);
203 model_
->Remove(selection_
[i
]);
209 case IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK
: {
210 content::RecordAction(
211 UserMetricsAction("BookmarkBar_ContextMenu_Add"));
214 const BookmarkNode
* parent
=
215 bookmarks::GetParentForNewNodes(parent_
, selection_
, &index
);
217 base::string16 title
;
218 chrome::GetURLAndTitleToBookmark(
219 browser_
->tab_strip_model()->GetActiveWebContents(),
221 BookmarkEditor::Show(parent_window_
,
223 BookmarkEditor::EditDetails::AddNodeInFolder(
224 parent
, index
, url
, title
),
225 BookmarkEditor::SHOW_TREE
);
229 case IDC_BOOKMARK_BAR_NEW_FOLDER
: {
230 content::RecordAction(
231 UserMetricsAction("BookmarkBar_ContextMenu_NewFolder"));
234 const BookmarkNode
* parent
=
235 bookmarks::GetParentForNewNodes(parent_
, selection_
, &index
);
236 BookmarkEditor::Show(
239 BookmarkEditor::EditDetails::AddFolder(parent
, index
),
240 BookmarkEditor::SHOW_TREE
);
244 case IDC_BOOKMARK_BAR_ALWAYS_SHOW
:
245 chrome::ToggleBookmarkBarWhenVisible(profile_
);
248 case IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
: {
249 PrefService
* prefs
= profile_
->GetPrefs();
251 bookmarks::prefs::kShowAppsShortcutInBookmarkBar
,
252 !prefs
->GetBoolean(bookmarks::prefs::kShowAppsShortcutInBookmarkBar
));
256 case IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
: {
257 PrefService
* prefs
= profile_
->GetPrefs();
259 bookmarks::prefs::kShowManagedBookmarksInBookmarkBar
,
261 bookmarks::prefs::kShowManagedBookmarksInBookmarkBar
));
265 case IDC_BOOKMARK_MANAGER
: {
266 content::RecordAction(UserMetricsAction("ShowBookmarkManager"));
267 if (selection_
.size() != 1)
268 chrome::ShowBookmarkManager(browser_
);
269 else if (selection_
[0]->is_folder())
270 chrome::ShowBookmarkManagerForNode(browser_
, selection_
[0]->id());
272 chrome::ShowBookmarkManagerForNode(browser_
, parent_
->id());
274 chrome::ShowBookmarkManager(browser_
);
279 bookmarks::CopyToClipboard(model_
, selection_
, true);
283 bookmarks::CopyToClipboard(model_
, selection_
, false);
288 const BookmarkNode
* paste_target
=
289 bookmarks::GetParentForNewNodes(parent_
, selection_
, &index
);
293 bookmarks::PasteFromClipboard(model_
, paste_target
, index
);
302 delegate_
->DidExecuteCommand(id
);
305 bool BookmarkContextMenuController::IsItemForCommandIdDynamic(int command_id
)
307 return command_id
== IDC_BOOKMARK_BAR_UNDO
||
308 command_id
== IDC_BOOKMARK_BAR_REDO
||
309 command_id
== IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
;
312 base::string16
BookmarkContextMenuController::GetLabelForCommandId(
313 int command_id
) const {
314 if (command_id
== IDC_BOOKMARK_BAR_UNDO
) {
315 return BookmarkUndoServiceFactory::GetForProfile(profile_
)->
316 undo_manager()->GetUndoLabel();
318 if (command_id
== IDC_BOOKMARK_BAR_REDO
) {
319 return BookmarkUndoServiceFactory::GetForProfile(profile_
)->
320 undo_manager()->GetRedoLabel();
322 if (command_id
== IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
) {
323 bookmarks::ManagedBookmarkService
* managed
=
324 ManagedBookmarkServiceFactory::GetForProfile(profile_
);
325 return l10n_util::GetStringFUTF16(IDS_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
,
326 managed
->managed_node()->GetTitle());
330 return base::string16();
333 bool BookmarkContextMenuController::IsCommandIdChecked(int command_id
) const {
334 PrefService
* prefs
= profile_
->GetPrefs();
335 if (command_id
== IDC_BOOKMARK_BAR_ALWAYS_SHOW
)
336 return prefs
->GetBoolean(bookmarks::prefs::kShowBookmarkBar
);
337 if (command_id
== IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
)
338 return prefs
->GetBoolean(
339 bookmarks::prefs::kShowManagedBookmarksInBookmarkBar
);
341 DCHECK_EQ(IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
, command_id
);
342 return prefs
->GetBoolean(bookmarks::prefs::kShowAppsShortcutInBookmarkBar
);
345 bool BookmarkContextMenuController::IsCommandIdEnabled(int command_id
) const {
346 PrefService
* prefs
= profile_
->GetPrefs();
348 bool is_root_node
= selection_
.size() == 1 &&
349 selection_
[0]->parent() == model_
->root_node();
350 bool can_edit
= prefs
->GetBoolean(bookmarks::prefs::kEditBookmarksEnabled
) &&
351 bookmarks::CanAllBeEditedByUser(model_
->client(), selection_
);
352 IncognitoModePrefs::Availability incognito_avail
=
353 IncognitoModePrefs::GetAvailability(prefs
);
355 switch (command_id
) {
356 case IDC_BOOKMARK_BAR_OPEN_INCOGNITO
:
357 return !profile_
->IsOffTheRecord() &&
358 incognito_avail
!= IncognitoModePrefs::DISABLED
;
360 case IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO
:
361 return chrome::HasBookmarkURLsAllowedInIncognitoMode(selection_
, profile_
)
363 !profile_
->IsOffTheRecord() &&
364 incognito_avail
!= IncognitoModePrefs::DISABLED
;
366 case IDC_BOOKMARK_BAR_OPEN_ALL
:
367 return chrome::HasBookmarkURLs(selection_
);
368 case IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW
:
369 return chrome::HasBookmarkURLs(selection_
) &&
370 incognito_avail
!= IncognitoModePrefs::FORCED
;
372 case IDC_BOOKMARK_BAR_RENAME_FOLDER
:
373 case IDC_BOOKMARK_BAR_EDIT
:
374 return selection_
.size() == 1 && !is_root_node
&& can_edit
;
376 case IDC_BOOKMARK_BAR_UNDO
:
378 BookmarkUndoServiceFactory::GetForProfile(profile_
)->
379 undo_manager()->undo_count() > 0;
381 case IDC_BOOKMARK_BAR_REDO
:
383 BookmarkUndoServiceFactory::GetForProfile(profile_
)->
384 undo_manager()->redo_count() > 0;
386 case IDC_BOOKMARK_BAR_REMOVE
:
387 return !selection_
.empty() && !is_root_node
&& can_edit
;
389 case IDC_BOOKMARK_BAR_NEW_FOLDER
:
390 case IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK
:
391 return can_edit
&& model_
->client()->CanBeEditedByUser(parent_
) &&
392 bookmarks::GetParentForNewNodes(parent_
, selection_
, NULL
) != NULL
;
394 case IDC_BOOKMARK_BAR_ALWAYS_SHOW
:
395 return !prefs
->IsManagedPreference(bookmarks::prefs::kShowBookmarkBar
);
397 case IDC_BOOKMARK_BAR_SHOW_APPS_SHORTCUT
:
398 return !prefs
->IsManagedPreference(
399 bookmarks::prefs::kShowAppsShortcutInBookmarkBar
);
403 return !selection_
.empty() && !is_root_node
&&
404 (command_id
== IDC_COPY
|| can_edit
);
407 // Paste to selection from the Bookmark Bar, to parent_ everywhere else
409 ((!selection_
.empty() &&
410 bookmarks::CanPasteFromClipboard(model_
, selection_
[0])) ||
411 bookmarks::CanPasteFromClipboard(model_
, parent_
));
416 bool BookmarkContextMenuController::IsCommandIdVisible(int command_id
) const {
417 if (command_id
== IDC_BOOKMARK_BAR_SHOW_MANAGED_BOOKMARKS
) {
418 // The option to hide the Managed Bookmarks folder is only available if
419 // there are any managed bookmarks configured at all.
420 bookmarks::ManagedBookmarkService
* managed
=
421 ManagedBookmarkServiceFactory::GetForProfile(profile_
);
422 return !managed
->managed_node()->empty();
428 bool BookmarkContextMenuController::GetAcceleratorForCommandId(
430 ui::Accelerator
* accelerator
) {
434 void BookmarkContextMenuController::BookmarkModelChanged() {
436 delegate_
->CloseMenu();